From e4b409364e4c493a66d4b2a6fe897075aa5c174e Mon Sep 17 00:00:00 2001 From: ctiller Date: Wed, 7 Jan 2015 12:13:17 -0800 Subject: [PATCH 01/29] Add a --forever flag, to continuously run tests as things change. Change on 2015/01/07 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83451760 --- Makefile | 37 +- build.json | 20 +- include/grpc/support/port_platform.h | 3 - include/grpc/support/time.h | 2 - src/compiler/ruby_generator.cc | 5 - src/core/channel/child_channel.c | 36 +- src/core/channel/child_channel.h | 3 +- src/core/channel/client_channel.c | 20 +- src/core/channel/client_setup.c | 5 +- src/core/httpcli/httpcli.c | 10 +- src/core/iomgr/alarm.c | 34 +- src/core/iomgr/alarm_internal.h | 5 +- src/core/iomgr/endpoint.c | 14 +- src/core/iomgr/endpoint.h | 17 +- src/core/iomgr/fd_posix.c | 274 -------- src/core/iomgr/fd_posix.h | 138 ---- src/core/iomgr/iomgr.c | 204 ------ src/core/iomgr/iomgr.h | 11 +- ...x.h => iomgr_completion_queue_interface.h} | 15 +- src/core/iomgr/iomgr_libevent.c | 652 ++++++++++++++++++ src/core/iomgr/iomgr_libevent.h | 206 ++++++ ...nternal.h => iomgr_libevent_use_threads.c} | 35 +- src/core/iomgr/{iomgr_posix.c => pollset.c} | 7 +- src/core/iomgr/pollset.h | 21 +- .../pollset_multipoller_with_poll_posix.c | 239 ------- src/core/iomgr/pollset_posix.c | 342 --------- src/core/iomgr/pollset_posix.h | 95 --- src/core/iomgr/resolve_address_posix.c | 6 +- src/core/iomgr/tcp_client_posix.c | 76 +- src/core/iomgr/tcp_posix.c | 67 +- src/core/iomgr/tcp_posix.h | 2 +- src/core/iomgr/tcp_server.h | 4 +- src/core/iomgr/tcp_server_posix.c | 38 +- src/core/security/credentials.c | 5 +- src/core/security/secure_endpoint.c | 15 +- src/core/security/secure_transport_setup.c | 12 +- src/core/security/server_secure_chttp2.c | 4 +- src/core/support/time.c | 15 - src/core/surface/call.c | 4 +- src/core/surface/completion_queue.c | 66 +- src/core/surface/server.c | 13 +- src/core/surface/server.h | 3 +- src/core/surface/server_chttp2.c | 4 +- src/core/transport/chttp2_transport.c | 5 +- src/ruby/Gemfile | 8 + src/ruby/README.md | 46 +- src/ruby/bin/interop/interop_client.rb | 25 +- src/ruby/bin/interop/interop_server.rb | 9 +- .../net/proto2/bridge/proto/message_set.pb.rb | 14 + .../bin/interop/net/proto2/proto/empty.pb.rb | 12 + .../bin/interop/test/cpp/interop/empty.rb | 44 -- .../bin/interop/test/cpp/interop/messages.rb | 86 --- src/ruby/bin/interop/test/cpp/interop/test.rb | 43 -- .../interop/test/cpp/interop/test_services.rb | 60 -- .../stubby/testing/proto/messages.pb.rb | 94 +++ .../stubby/testing/proto/test.pb.rb | 30 + src/ruby/bin/math.pb.rb | 65 ++ src/ruby/bin/math.proto | 14 +- src/ruby/bin/math.rb | 61 -- src/ruby/bin/math_client.rb | 6 +- src/ruby/bin/math_server.rb | 6 +- src/ruby/bin/math_services.rb | 56 -- src/ruby/bin/noproto_client.rb | 62 +- src/ruby/bin/noproto_server.rb | 54 +- src/ruby/grpc.gemspec | 2 +- src/ruby/lib/grpc.rb | 1 + src/ruby/lib/grpc/generic/service.rb | 11 +- src/ruby/spec/generic/service_spec.rb | 33 - templates/Makefile.template | 17 +- test/core/end2end/cq_verifier.c | 7 +- .../end2end/fixtures/chttp2_socket_pair.c | 1 - .../chttp2_socket_pair_one_byte_at_a_time.c | 1 - .../core/end2end/tests/invoke_large_request.c | 2 +- .../end2end/tests/max_concurrent_streams.c | 56 +- test/core/iomgr/alarm_list_test.c | 50 +- test/core/iomgr/alarm_test.c | 26 +- test/core/iomgr/endpoint_tests.c | 113 ++- test/core/iomgr/fd_posix_test.c | 127 +++- test/core/iomgr/tcp_client_posix_test.c | 2 +- test/core/iomgr/tcp_posix_test.c | 16 +- test/core/iomgr/tcp_server_posix_test.c | 6 +- test/core/security/secure_endpoint_test.c | 5 +- vsprojects/vs2013/grpc.vcxproj | 24 +- vsprojects/vs2013/grpc_unsecure.vcxproj | 24 +- 84 files changed, 1775 insertions(+), 2333 deletions(-) delete mode 100644 src/core/iomgr/fd_posix.c delete mode 100644 src/core/iomgr/fd_posix.h delete mode 100644 src/core/iomgr/iomgr.c rename src/core/iomgr/{iomgr_posix.h => iomgr_completion_queue_interface.h} (79%) create mode 100644 src/core/iomgr/iomgr_libevent.c create mode 100644 src/core/iomgr/iomgr_libevent.h rename src/core/iomgr/{iomgr_internal.h => iomgr_libevent_use_threads.c} (67%) rename src/core/iomgr/{iomgr_posix.c => pollset.c} (89%) delete mode 100644 src/core/iomgr/pollset_multipoller_with_poll_posix.c delete mode 100644 src/core/iomgr/pollset_posix.c delete mode 100644 src/core/iomgr/pollset_posix.h create mode 100755 src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb create mode 100755 src/ruby/bin/interop/net/proto2/proto/empty.pb.rb delete mode 100644 src/ruby/bin/interop/test/cpp/interop/empty.rb delete mode 100644 src/ruby/bin/interop/test/cpp/interop/messages.rb delete mode 100644 src/ruby/bin/interop/test/cpp/interop/test.rb delete mode 100644 src/ruby/bin/interop/test/cpp/interop/test_services.rb create mode 100755 src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb create mode 100755 src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb create mode 100755 src/ruby/bin/math.pb.rb delete mode 100644 src/ruby/bin/math.rb delete mode 100644 src/ruby/bin/math_services.rb diff --git a/Makefile b/Makefile index 829241b9d5b..49b0bd629de 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,7 @@ CPPFLAGS += -g -fPIC -Wall -Werror -Wno-long-long LDFLAGS += -g -pthread -fPIC INCLUDES = . include gens -LIBS = rt m z pthread +LIBS = rt m z event event_pthreads pthread LIBSXX = protobuf LIBS_PROTOC = protoc protobuf @@ -143,12 +143,20 @@ else IS_GIT_FOLDER = true endif +EVENT2_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/event2.c -levent $(LDFLAGS) OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS) ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) +HAS_SYSTEM_EVENT2 = $(shell $(EVENT2_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false) +ifeq ($(wildcard third_party/libevent/include/event2/event.h),) +HAS_EMBEDDED_EVENT2 = false +else +HAS_EMBEDDED_EVENT2 = true +endif + ifeq ($(wildcard third_party/openssl/ssl/ssl.h),) HAS_EMBEDDED_OPENSSL_ALPN = false else @@ -161,6 +169,12 @@ else HAS_EMBEDDED_ZLIB = true endif +ifneq ($(SYSTEM),MINGW32) +ifeq ($(HAS_SYSTEM_EVENT2),false) +DEP_MISSING += libevent +endif +endif + ifeq ($(HAS_SYSTEM_ZLIB),false) ifeq ($(HAS_EMBEDDED_ZLIB),true) ZLIB_DEP = third_party/zlib/libz.a @@ -452,6 +466,7 @@ chttp2_socket_pair_one_byte_at_a_time_thread_stress_test: bins/$(CONFIG)/chttp2_ chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test run_dep_checks: + $(EVENT2_CHECK_CMD) || true $(OPENSSL_ALPN_CHECK_CMD) || true $(ZLIB_CHECK_CMD) || true @@ -1214,11 +1229,9 @@ LIBGRPC_SRC = \ src/core/iomgr/alarm_heap.c \ src/core/iomgr/endpoint.c \ src/core/iomgr/endpoint_pair_posix.c \ - src/core/iomgr/fd_posix.c \ - src/core/iomgr/iomgr.c \ - src/core/iomgr/iomgr_posix.c \ - src/core/iomgr/pollset_multipoller_with_poll_posix.c \ - src/core/iomgr/pollset_posix.c \ + src/core/iomgr/iomgr_libevent.c \ + src/core/iomgr/iomgr_libevent_use_threads.c \ + src/core/iomgr/pollset.c \ src/core/iomgr/resolve_address_posix.c \ src/core/iomgr/sockaddr_utils.c \ src/core/iomgr/socket_utils_common_posix.c \ @@ -1264,8 +1277,8 @@ LIBGRPC_SRC = \ src/core/transport/chttp2/stream_encoder.c \ src/core/transport/chttp2/stream_map.c \ src/core/transport/chttp2/timeout_encoding.c \ - src/core/transport/chttp2/varint.c \ src/core/transport/chttp2_transport.c \ + src/core/transport/chttp2/varint.c \ src/core/transport/metadata.c \ src/core/transport/stream_op.c \ src/core/transport/transport.c \ @@ -1366,11 +1379,9 @@ LIBGRPC_UNSECURE_SRC = \ src/core/iomgr/alarm_heap.c \ src/core/iomgr/endpoint.c \ src/core/iomgr/endpoint_pair_posix.c \ - src/core/iomgr/fd_posix.c \ - src/core/iomgr/iomgr.c \ - src/core/iomgr/iomgr_posix.c \ - src/core/iomgr/pollset_multipoller_with_poll_posix.c \ - src/core/iomgr/pollset_posix.c \ + src/core/iomgr/iomgr_libevent.c \ + src/core/iomgr/iomgr_libevent_use_threads.c \ + src/core/iomgr/pollset.c \ src/core/iomgr/resolve_address_posix.c \ src/core/iomgr/sockaddr_utils.c \ src/core/iomgr/socket_utils_common_posix.c \ @@ -1416,8 +1427,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/transport/chttp2/stream_encoder.c \ src/core/transport/chttp2/stream_map.c \ src/core/transport/chttp2/timeout_encoding.c \ - src/core/transport/chttp2/varint.c \ src/core/transport/chttp2_transport.c \ + src/core/transport/chttp2/varint.c \ src/core/transport/metadata.c \ src/core/transport/stream_op.c \ src/core/transport/transport.c \ diff --git a/build.json b/build.json index e0e05c8eaf4..e0bf2806359 100644 --- a/build.json +++ b/build.json @@ -35,11 +35,9 @@ "src/core/iomgr/alarm_heap.c", "src/core/iomgr/endpoint.c", "src/core/iomgr/endpoint_pair_posix.c", - "src/core/iomgr/fd_posix.c", - "src/core/iomgr/iomgr.c", - "src/core/iomgr/iomgr_posix.c", - "src/core/iomgr/pollset_multipoller_with_poll_posix.c", - "src/core/iomgr/pollset_posix.c", + "src/core/iomgr/iomgr_libevent.c", + "src/core/iomgr/iomgr_libevent_use_threads.c", + "src/core/iomgr/pollset.c", "src/core/iomgr/resolve_address_posix.c", "src/core/iomgr/sockaddr_utils.c", "src/core/iomgr/socket_utils_common_posix.c", @@ -85,8 +83,8 @@ "src/core/transport/chttp2/stream_encoder.c", "src/core/transport/chttp2/stream_map.c", "src/core/transport/chttp2/timeout_encoding.c", - "src/core/transport/chttp2/varint.c", "src/core/transport/chttp2_transport.c", + "src/core/transport/chttp2/varint.c", "src/core/transport/metadata.c", "src/core/transport/stream_op.c", "src/core/transport/transport.c", @@ -122,12 +120,10 @@ "src/core/iomgr/alarm_internal.h", "src/core/iomgr/endpoint.h", "src/core/iomgr/endpoint_pair.h", - "src/core/iomgr/fd_posix.h", + "src/core/iomgr/iomgr_completion_queue_interface.h", "src/core/iomgr/iomgr.h", - "src/core/iomgr/iomgr_internal.h", - "src/core/iomgr/iomgr_posix.h", + "src/core/iomgr/iomgr_libevent.h", "src/core/iomgr/pollset.h", - "src/core/iomgr/pollset_posix.h", "src/core/iomgr/resolve_address.h", "src/core/iomgr/sockaddr.h", "src/core/iomgr/sockaddr_posix.h", @@ -152,9 +148,9 @@ "src/core/surface/server.h", "src/core/surface/surface_trace.h", "src/core/transport/chttp2/bin_encoder.h", - "src/core/transport/chttp2/frame.h", "src/core/transport/chttp2/frame_data.h", "src/core/transport/chttp2/frame_goaway.h", + "src/core/transport/chttp2/frame.h", "src/core/transport/chttp2/frame_ping.h", "src/core/transport/chttp2/frame_rst_stream.h", "src/core/transport/chttp2/frame_settings.h", @@ -167,8 +163,8 @@ "src/core/transport/chttp2/stream_encoder.h", "src/core/transport/chttp2/stream_map.h", "src/core/transport/chttp2/timeout_encoding.h", - "src/core/transport/chttp2/varint.h", "src/core/transport/chttp2_transport.h", + "src/core/transport/chttp2/varint.h", "src/core/transport/metadata.h", "src/core/transport/stream_op.h", "src/core/transport/transport.h", diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h index 27a7b5529f7..9e5c9ff2ace 100644 --- a/include/grpc/support/port_platform.h +++ b/include/grpc/support/port_platform.h @@ -54,7 +54,6 @@ #define GPR_CPU_LINUX 1 #define GPR_GCC_SYNC 1 #define GPR_LIBEVENT 1 -#define GPR_POSIX_MULTIPOLL_WITH_POLL 1 #define GPR_POSIX_SOCKET 1 #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 @@ -66,7 +65,6 @@ #define GPR_GCC_ATOMIC 1 #define GPR_LIBEVENT 1 #define GPR_LINUX 1 -#define GPR_POSIX_MULTIPOLL_WITH_POLL 1 #define GPR_POSIX_SOCKET 1 #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_STRING 1 @@ -82,7 +80,6 @@ #define GPR_GCC_ATOMIC 1 #define GPR_LIBEVENT 1 #define GPR_POSIX_LOG 1 -#define GPR_POSIX_MULTIPOLL_WITH_POLL 1 #define GPR_POSIX_SOCKET 1 #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h index 41d1e88dc94..5a57d947681 100644 --- a/include/grpc/support/time.h +++ b/include/grpc/support/time.h @@ -94,8 +94,6 @@ gpr_timespec gpr_time_from_seconds(long x); gpr_timespec gpr_time_from_minutes(long x); gpr_timespec gpr_time_from_hours(long x); -gpr_int32 gpr_time_to_millis(gpr_timespec timespec); - /* Return 1 if two times are equal or within threshold of each other, 0 otherwise */ int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold); diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc index 20485b47a5f..c5c58847363 100644 --- a/src/compiler/ruby_generator.cc +++ b/src/compiler/ruby_generator.cc @@ -104,11 +104,6 @@ void PrintService(const ServiceDescriptor* service, const string& package, out->Print("\n"); out->Print("self.marshal_class_method = :encode\n"); out->Print("self.unmarshal_class_method = :decode\n"); - map pkg_vars = ListToDict({ - "service.name", service->name(), - "pkg.name", package, - }); - out->Print(pkg_vars, "self.service_name = '$pkg.name$.$service.name$'\n"); out->Print("\n"); for (int i = 0; i < service->method_count(); ++i) { PrintMethod(service->method(i), package, out); diff --git a/src/core/channel/child_channel.c b/src/core/channel/child_channel.c index 3778f4fb88f..e67b8236974 100644 --- a/src/core/channel/child_channel.c +++ b/src/core/channel/child_channel.c @@ -85,19 +85,19 @@ static void lb_channel_op(grpc_channel_element *elem, grpc_channel_op *op) { lb_channel_data *chand = elem->channel_data; grpc_channel_element *back; - int calling_back = 0; switch (op->dir) { case GRPC_CALL_UP: gpr_mu_lock(&chand->mu); back = chand->back; - if (back) { - chand->calling_back++; - calling_back = 1; - } + if (back) chand->calling_back++; gpr_mu_unlock(&chand->mu); if (back) { back->filter->channel_op(chand->back, elem, op); + gpr_mu_lock(&chand->mu); + chand->calling_back--; + gpr_cv_broadcast(&chand->cv); + gpr_mu_unlock(&chand->mu); } else if (op->type == GRPC_TRANSPORT_GOAWAY) { gpr_slice_unref(op->data.goaway.message); } @@ -107,27 +107,23 @@ static void lb_channel_op(grpc_channel_element *elem, break; } - gpr_mu_lock(&chand->mu); switch (op->type) { case GRPC_TRANSPORT_CLOSED: + gpr_mu_lock(&chand->mu); chand->disconnected = 1; maybe_destroy_channel(grpc_channel_stack_from_top_element(elem)); + gpr_mu_unlock(&chand->mu); break; case GRPC_CHANNEL_GOAWAY: + gpr_mu_lock(&chand->mu); chand->sent_goaway = 1; + gpr_mu_unlock(&chand->mu); break; case GRPC_CHANNEL_DISCONNECT: case GRPC_TRANSPORT_GOAWAY: case GRPC_ACCEPT_CALL: break; } - - if (calling_back) { - chand->calling_back--; - gpr_cv_signal(&chand->cv); - maybe_destroy_channel(grpc_channel_stack_from_top_element(elem)); - } - gpr_mu_unlock(&chand->mu); } /* Constructor for call_data */ @@ -181,9 +177,7 @@ const grpc_channel_filter grpc_child_channel_top_filter = { #define LINK_BACK_ELEM_FROM_CALL(call) grpc_call_stack_element((call), 0) -static void finally_destroy_channel(void *c, int success) { - /* ignore success or not... this is a destruction callback and will only - happen once - the only purpose here is to release resources */ +static void finally_destroy_channel(void *c, grpc_iomgr_cb_status status) { grpc_child_channel *channel = c; lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data; /* wait for the initiator to leave the mutex */ @@ -193,7 +187,7 @@ static void finally_destroy_channel(void *c, int success) { gpr_free(channel); } -static void send_farewells(void *c, int success) { +static void send_farewells(void *c, grpc_iomgr_cb_status status) { grpc_child_channel *channel = c; grpc_channel_element *lbelem = LINK_BACK_ELEM_FROM_CHANNEL(channel); lb_channel_data *chand = lbelem->channel_data; @@ -227,7 +221,7 @@ static void send_farewells(void *c, int success) { static void maybe_destroy_channel(grpc_child_channel *channel) { lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data; if (chand->destroyed && chand->disconnected && chand->active_calls == 0 && - !chand->sending_farewell && !chand->calling_back) { + !chand->sending_farewell) { grpc_iomgr_add_callback(finally_destroy_channel, channel); } else if (chand->destroyed && !chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && @@ -255,16 +249,14 @@ grpc_child_channel *grpc_child_channel_create( return stk; } -void grpc_child_channel_destroy(grpc_child_channel *channel, - int wait_for_callbacks) { +void grpc_child_channel_destroy(grpc_child_channel *channel) { grpc_channel_element *lbelem = LINK_BACK_ELEM_FROM_CHANNEL(channel); lb_channel_data *chand = lbelem->channel_data; gpr_mu_lock(&chand->mu); - while (wait_for_callbacks && chand->calling_back) { + while (chand->calling_back) { gpr_cv_wait(&chand->cv, &chand->mu, gpr_inf_future); } - chand->back = NULL; chand->destroyed = 1; maybe_destroy_channel(channel); diff --git a/src/core/channel/child_channel.h b/src/core/channel/child_channel.h index 3ba4c1b8a9e..9fb2a17e29d 100644 --- a/src/core/channel/child_channel.h +++ b/src/core/channel/child_channel.h @@ -53,8 +53,7 @@ void grpc_child_channel_handle_op(grpc_child_channel *channel, grpc_channel_op *op); grpc_channel_element *grpc_child_channel_get_bottom_element( grpc_child_channel *channel); -void grpc_child_channel_destroy(grpc_child_channel *channel, - int wait_for_callbacks); +void grpc_child_channel_destroy(grpc_child_channel *channel); grpc_child_call *grpc_child_channel_create_call(grpc_child_channel *channel, grpc_call_element *parent); diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c index 46283835a05..fd883a08cab 100644 --- a/src/core/channel/client_channel.c +++ b/src/core/channel/client_channel.c @@ -294,6 +294,14 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, } } +static void finally_destroy_channel(void *arg, grpc_iomgr_cb_status status) { + grpc_child_channel_destroy(arg); +} + +static void destroy_channel_later(grpc_child_channel *channel) { + grpc_iomgr_add_callback(finally_destroy_channel, channel); +} + static void channel_op(grpc_channel_element *elem, grpc_channel_element *from_elem, grpc_channel_op *op) { channel_data *chand = elem->channel_data; @@ -309,7 +317,7 @@ static void channel_op(grpc_channel_element *elem, gpr_mu_unlock(&chand->mu); if (child_channel) { grpc_child_channel_handle_op(child_channel, op); - grpc_child_channel_destroy(child_channel, 1); + destroy_channel_later(child_channel); } else { gpr_slice_unref(op->data.goaway.message); } @@ -321,7 +329,7 @@ static void channel_op(grpc_channel_element *elem, chand->active_child = NULL; gpr_mu_unlock(&chand->mu); if (child_channel) { - grpc_child_channel_destroy(child_channel, 1); + destroy_channel_later(child_channel); } break; case GRPC_TRANSPORT_GOAWAY: @@ -336,7 +344,7 @@ static void channel_op(grpc_channel_element *elem, } gpr_mu_unlock(&chand->mu); if (child_channel) { - grpc_child_channel_destroy(child_channel, 0); + destroy_channel_later(child_channel); } gpr_slice_unref(op->data.goaway.message); break; @@ -352,7 +360,7 @@ static void channel_op(grpc_channel_element *elem, } gpr_mu_unlock(&chand->mu); if (child_channel) { - grpc_child_channel_destroy(child_channel, 0); + destroy_channel_later(child_channel); } break; default: @@ -437,7 +445,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) { grpc_transport_setup_cancel(chand->transport_setup); if (chand->active_child) { - grpc_child_channel_destroy(chand->active_child, 1); + grpc_child_channel_destroy(chand->active_child); chand->active_child = NULL; } @@ -541,7 +549,7 @@ grpc_transport_setup_result grpc_client_channel_transport_setup_complete( gpr_free(child_filters); if (old_active) { - grpc_child_channel_destroy(old_active, 1); + grpc_child_channel_destroy(old_active); } return result; diff --git a/src/core/channel/client_setup.c b/src/core/channel/client_setup.c index ebaf816902b..b1194e278de 100644 --- a/src/core/channel/client_setup.c +++ b/src/core/channel/client_setup.c @@ -166,7 +166,8 @@ int grpc_client_setup_request_should_continue(grpc_client_setup_request *r) { return result; } -static void backoff_alarm_done(void *arg /* grpc_client_setup */, int success) { +static void backoff_alarm_done(void *arg /* grpc_client_setup */, + grpc_iomgr_cb_status status) { grpc_client_setup *s = arg; grpc_client_setup_request *r = gpr_malloc(sizeof(grpc_client_setup_request)); r->setup = s; @@ -176,7 +177,7 @@ static void backoff_alarm_done(void *arg /* grpc_client_setup */, int success) { gpr_mu_lock(&s->mu); s->active_request = r; s->in_alarm = 0; - if (!success) { + if (status != GRPC_CALLBACK_SUCCESS) { if (0 == --s->refs) { gpr_mu_unlock(&s->mu); destroy_setup(s); diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index 2143eeb63d0..06d73e40f52 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -101,11 +101,12 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, switch (status) { case GRPC_ENDPOINT_CB_OK: - grpc_endpoint_notify_on_read(req->ep, on_read, req); + grpc_endpoint_notify_on_read(req->ep, on_read, req, gpr_inf_future); break; case GRPC_ENDPOINT_CB_EOF: case GRPC_ENDPOINT_CB_ERROR: case GRPC_ENDPOINT_CB_SHUTDOWN: + case GRPC_ENDPOINT_CB_TIMED_OUT: if (!req->have_read_byte) { next_address(req); } else { @@ -122,7 +123,7 @@ done: static void on_written(internal_request *req) { gpr_log(GPR_DEBUG, "%s", __FUNCTION__); - grpc_endpoint_notify_on_read(req->ep, on_read, req); + grpc_endpoint_notify_on_read(req->ep, on_read, req, gpr_inf_future); } static void done_write(void *arg, grpc_endpoint_cb_status status) { @@ -135,6 +136,7 @@ static void done_write(void *arg, grpc_endpoint_cb_status status) { case GRPC_ENDPOINT_CB_EOF: case GRPC_ENDPOINT_CB_SHUTDOWN: case GRPC_ENDPOINT_CB_ERROR: + case GRPC_ENDPOINT_CB_TIMED_OUT: next_address(req); break; } @@ -143,8 +145,8 @@ static void done_write(void *arg, grpc_endpoint_cb_status status) { static void start_write(internal_request *req) { gpr_slice_ref(req->request_text); gpr_log(GPR_DEBUG, "%s", __FUNCTION__); - switch ( - grpc_endpoint_write(req->ep, &req->request_text, 1, done_write, req)) { + switch (grpc_endpoint_write(req->ep, &req->request_text, 1, done_write, req, + gpr_inf_future)) { case GRPC_ENDPOINT_WRITE_DONE: on_written(req); break; diff --git a/src/core/iomgr/alarm.c b/src/core/iomgr/alarm.c index 26648793238..b7238f716a9 100644 --- a/src/core/iomgr/alarm.c +++ b/src/core/iomgr/alarm.c @@ -71,8 +71,8 @@ static shard_type g_shards[NUM_SHARDS]; /* Protected by g_mu */ static shard_type *g_shard_queue[NUM_SHARDS]; -static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now, - gpr_timespec *next, int success); +static int run_some_expired_alarms(gpr_timespec now, + grpc_iomgr_cb_status status); static gpr_timespec compute_min_deadline(shard_type *shard) { return grpc_alarm_heap_is_empty(&shard->heap) @@ -102,7 +102,7 @@ void grpc_alarm_list_init(gpr_timespec now) { void grpc_alarm_list_shutdown() { int i; - while (run_some_expired_alarms(NULL, gpr_inf_future, NULL, 0)) + while (run_some_expired_alarms(gpr_inf_future, GRPC_CALLBACK_CANCELLED)) ; for (i = 0; i < NUM_SHARDS; i++) { shard_type *shard = &g_shards[i]; @@ -233,7 +233,7 @@ void grpc_alarm_cancel(grpc_alarm *alarm) { gpr_mu_unlock(&shard->mu); if (triggered) { - alarm->cb(alarm->cb_arg, 0); + alarm->cb(alarm->cb_arg, GRPC_CALLBACK_CANCELLED); } } @@ -299,8 +299,8 @@ static size_t pop_alarms(shard_type *shard, gpr_timespec now, return n; } -static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now, - gpr_timespec *next, int success) { +static int run_some_expired_alarms(gpr_timespec now, + grpc_iomgr_cb_status status) { size_t n = 0; size_t i; grpc_alarm *alarms[MAX_ALARMS_PER_CHECK]; @@ -329,35 +329,19 @@ static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now, note_deadline_change(g_shard_queue[0]); } - if (next) { - *next = gpr_time_min(*next, g_shard_queue[0]->min_deadline); - } - gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_checker_mu); - } else if (next) { - gpr_mu_lock(&g_mu); - *next = gpr_time_min(*next, g_shard_queue[0]->min_deadline); - gpr_mu_unlock(&g_mu); - } - - if (n && drop_mu) { - gpr_mu_unlock(drop_mu); } for (i = 0; i < n; i++) { - alarms[i]->cb(alarms[i]->cb_arg, success); - } - - if (n && drop_mu) { - gpr_mu_lock(drop_mu); + alarms[i]->cb(alarms[i]->cb_arg, status); } return n; } -int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next) { - return run_some_expired_alarms(drop_mu, now, next, 1); +int grpc_alarm_check(gpr_timespec now) { + return run_some_expired_alarms(now, GRPC_CALLBACK_SUCCESS); } gpr_timespec grpc_alarm_list_next_timeout() { diff --git a/src/core/iomgr/alarm_internal.h b/src/core/iomgr/alarm_internal.h index 12b6ab4286d..e605ff84f9e 100644 --- a/src/core/iomgr/alarm_internal.h +++ b/src/core/iomgr/alarm_internal.h @@ -34,12 +34,9 @@ #ifndef __GRPC_INTERNAL_IOMGR_ALARM_INTERNAL_H_ #define __GRPC_INTERNAL_IOMGR_ALARM_INTERNAL_H_ -#include -#include - /* iomgr internal api for dealing with alarms */ -int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next); +int grpc_alarm_check(gpr_timespec now); void grpc_alarm_list_init(gpr_timespec now); void grpc_alarm_list_shutdown(); diff --git a/src/core/iomgr/endpoint.c b/src/core/iomgr/endpoint.c index 9e5d56389d2..f1944bf672c 100644 --- a/src/core/iomgr/endpoint.c +++ b/src/core/iomgr/endpoint.c @@ -34,16 +34,14 @@ #include "src/core/iomgr/endpoint.h" void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data) { - ep->vtable->notify_on_read(ep, cb, user_data); + void *user_data, gpr_timespec deadline) { + ep->vtable->notify_on_read(ep, cb, user_data, deadline); } -grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { - return ep->vtable->write(ep, slices, nslices, cb, user_data); +grpc_endpoint_write_status grpc_endpoint_write( + grpc_endpoint *ep, gpr_slice *slices, size_t nslices, + grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline) { + return ep->vtable->write(ep, slices, nslices, cb, user_data, deadline); } void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h index ec86d9a1460..bbd800bea85 100644 --- a/src/core/iomgr/endpoint.h +++ b/src/core/iomgr/endpoint.h @@ -48,7 +48,8 @@ typedef enum grpc_endpoint_cb_status { GRPC_ENDPOINT_CB_OK = 0, /* Call completed successfully */ GRPC_ENDPOINT_CB_EOF, /* Call completed successfully, end of file reached */ GRPC_ENDPOINT_CB_SHUTDOWN, /* Call interrupted by shutdown */ - GRPC_ENDPOINT_CB_ERROR /* Call interrupted by socket error */ + GRPC_ENDPOINT_CB_ERROR, /* Call interrupted by socket error */ + GRPC_ENDPOINT_CB_TIMED_OUT /* Call timed out */ } grpc_endpoint_cb_status; typedef enum grpc_endpoint_write_status { @@ -65,10 +66,10 @@ typedef void (*grpc_endpoint_write_cb)(void *user_data, struct grpc_endpoint_vtable { void (*notify_on_read)(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data); + void *user_data, gpr_timespec deadline); grpc_endpoint_write_status (*write)(grpc_endpoint *ep, gpr_slice *slices, size_t nslices, grpc_endpoint_write_cb cb, - void *user_data); + void *user_data, gpr_timespec deadline); void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset); void (*shutdown)(grpc_endpoint *ep); void (*destroy)(grpc_endpoint *ep); @@ -76,7 +77,7 @@ struct grpc_endpoint_vtable { /* When data is available on the connection, calls the callback with slices. */ void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data); + void *user_data, gpr_timespec deadline); /* Write slices out to the socket. @@ -84,11 +85,9 @@ void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, returns GRPC_ENDPOINT_WRITE_DONE. Otherwise it returns GRPC_ENDPOINT_WRITE_PENDING and calls cb when the connection is ready for more data. */ -grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data); +grpc_endpoint_write_status grpc_endpoint_write( + grpc_endpoint *ep, gpr_slice *slices, size_t nslices, + grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline); /* Causes any pending read/write callbacks to run immediately with GRPC_ENDPOINT_CB_SHUTDOWN status */ diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c deleted file mode 100644 index 3cd2f9a8e0c..00000000000 --- a/src/core/iomgr/fd_posix.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/fd_posix.h" - -#include -#include - -#include "src/core/iomgr/iomgr_internal.h" -#include -#include -#include - -enum descriptor_state { NOT_READY, READY, WAITING }; - -static void destroy(grpc_fd *fd) { - grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data); - gpr_mu_destroy(&fd->set_state_mu); - gpr_free(fd->watchers); - gpr_free(fd); - grpc_iomgr_unref(); -} - -static void ref_by(grpc_fd *fd, int n) { - gpr_atm_no_barrier_fetch_add(&fd->refst, n); -} - -static void unref_by(grpc_fd *fd, int n) { - if (gpr_atm_full_fetch_add(&fd->refst, -n) == n) { - destroy(fd); - } -} - -static void do_nothing(void *ignored, int success) {} - -grpc_fd *grpc_fd_create(int fd) { - grpc_fd *r = gpr_malloc(sizeof(grpc_fd)); - grpc_iomgr_ref(); - gpr_atm_rel_store(&r->refst, 1); - gpr_atm_rel_store(&r->readst.state, NOT_READY); - gpr_atm_rel_store(&r->writest.state, NOT_READY); - gpr_mu_init(&r->set_state_mu); - gpr_mu_init(&r->watcher_mu); - gpr_atm_rel_store(&r->shutdown, 0); - r->fd = fd; - r->watchers = NULL; - r->watcher_count = 0; - r->watcher_capacity = 0; - grpc_pollset_add_fd(grpc_backup_pollset(), r); - return r; -} - -int grpc_fd_is_orphaned(grpc_fd *fd) { - return (gpr_atm_acq_load(&fd->refst) & 1) == 0; -} - -static void wake_watchers(grpc_fd *fd) { - size_t i, n; - gpr_mu_lock(&fd->watcher_mu); - n = fd->watcher_count; - for (i = 0; i < n; i++) { - grpc_pollset_force_kick(fd->watchers[i]); - } - gpr_mu_unlock(&fd->watcher_mu); -} - -void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) { - fd->on_done = on_done ? on_done : do_nothing; - fd->on_done_user_data = user_data; - ref_by(fd, 1); /* remove active status, but keep referenced */ - wake_watchers(fd); - close(fd->fd); - unref_by(fd, 2); /* drop the reference */ -} - -/* increment refcount by two to avoid changing the orphan bit */ -void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); } - -void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); } - -typedef struct { - grpc_iomgr_cb_func cb; - void *arg; -} callback; - -static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success, - int allow_synchronous_callback) { - if (allow_synchronous_callback) { - cb(arg, success); - } else { - grpc_iomgr_add_delayed_callback(cb, arg, success); - } -} - -static void make_callbacks(callback *callbacks, size_t n, int success, - int allow_synchronous_callback) { - size_t i; - for (i = 0; i < n; i++) { - make_callback(callbacks[i].cb, callbacks[i].arg, success, - allow_synchronous_callback); - } -} - -static void notify_on(grpc_fd *fd, grpc_fd_state *st, grpc_iomgr_cb_func cb, - void *arg, int allow_synchronous_callback) { - switch ((enum descriptor_state)gpr_atm_acq_load(&st->state)) { - case NOT_READY: - /* There is no race if the descriptor is already ready, so we skip - the interlocked op in that case. As long as the app doesn't - try to set the same upcall twice (which it shouldn't) then - oldval should never be anything other than READY or NOT_READY. We - don't - check for user error on the fast path. */ - st->cb = cb; - st->cb_arg = arg; - if (gpr_atm_rel_cas(&st->state, NOT_READY, WAITING)) { - /* swap was successful -- the closure will run after the next - set_ready call. NOTE: we don't have an ABA problem here, - since we should never have concurrent calls to the same - notify_on function. */ - wake_watchers(fd); - return; - } - /* swap was unsuccessful due to an intervening set_ready call. - Fall through to the READY code below */ - case READY: - assert(gpr_atm_acq_load(&st->state) == READY); - gpr_atm_rel_store(&st->state, NOT_READY); - make_callback(cb, arg, !gpr_atm_acq_load(&fd->shutdown), - allow_synchronous_callback); - return; - case WAITING: - /* upcallptr was set to a different closure. This is an error! */ - gpr_log(GPR_ERROR, - "User called a notify_on function with a previous callback still " - "pending"); - abort(); - } - gpr_log(GPR_ERROR, "Corrupt memory in &st->state"); - abort(); -} - -static void set_ready_locked(grpc_fd_state *st, callback *callbacks, - size_t *ncallbacks) { - callback *c; - - switch ((enum descriptor_state)gpr_atm_acq_load(&st->state)) { - case NOT_READY: - if (gpr_atm_rel_cas(&st->state, NOT_READY, READY)) { - /* swap was successful -- the closure will run after the next - notify_on call. */ - return; - } - /* swap was unsuccessful due to an intervening set_ready call. - Fall through to the WAITING code below */ - case WAITING: - assert(gpr_atm_acq_load(&st->state) == WAITING); - c = &callbacks[(*ncallbacks)++]; - c->cb = st->cb; - c->arg = st->cb_arg; - gpr_atm_rel_store(&st->state, NOT_READY); - return; - case READY: - /* duplicate ready, ignore */ - return; - } -} - -static void set_ready(grpc_fd *fd, grpc_fd_state *st, - int allow_synchronous_callback) { - /* only one set_ready can be active at once (but there may be a racing - notify_on) */ - int success; - callback cb; - size_t ncb = 0; - gpr_mu_lock(&fd->set_state_mu); - set_ready_locked(st, &cb, &ncb); - gpr_mu_unlock(&fd->set_state_mu); - success = !gpr_atm_acq_load(&fd->shutdown); - make_callbacks(&cb, ncb, success, allow_synchronous_callback); -} - -void grpc_fd_shutdown(grpc_fd *fd) { - callback cb[2]; - size_t ncb = 0; - gpr_mu_lock(&fd->set_state_mu); - GPR_ASSERT(!gpr_atm_acq_load(&fd->shutdown)); - gpr_atm_rel_store(&fd->shutdown, 1); - set_ready_locked(&fd->readst, cb, &ncb); - set_ready_locked(&fd->writest, cb, &ncb); - gpr_mu_unlock(&fd->set_state_mu); - make_callbacks(cb, ncb, 0, 0); -} - -void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_cb_func read_cb, - void *read_cb_arg) { - notify_on(fd, &fd->readst, read_cb, read_cb_arg, 0); -} - -void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, - void *write_cb_arg) { - notify_on(fd, &fd->writest, write_cb, write_cb_arg, 0); -} - -gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, - gpr_uint32 read_mask, gpr_uint32 write_mask) { - /* keep track of pollers that have requested our events, in case they change - */ - gpr_mu_lock(&fd->watcher_mu); - if (fd->watcher_capacity == fd->watcher_count) { - fd->watcher_capacity = - GPR_MAX(fd->watcher_capacity + 8, fd->watcher_capacity * 3 / 2); - fd->watchers = gpr_realloc(fd->watchers, - fd->watcher_capacity * sizeof(grpc_pollset *)); - } - fd->watchers[fd->watcher_count++] = pollset; - gpr_mu_unlock(&fd->watcher_mu); - - return (gpr_atm_acq_load(&fd->readst.state) != READY ? read_mask : 0) | - (gpr_atm_acq_load(&fd->writest.state) != READY ? write_mask : 0); -} - -void grpc_fd_end_poll(grpc_fd *fd, grpc_pollset *pollset) { - size_t r, w, n; - - gpr_mu_lock(&fd->watcher_mu); - n = fd->watcher_count; - for (r = 0, w = 0; r < n; r++) { - if (fd->watchers[r] == pollset) { - fd->watcher_count--; - continue; - } - fd->watchers[w++] = fd->watchers[r]; - } - gpr_mu_unlock(&fd->watcher_mu); -} - -void grpc_fd_become_readable(grpc_fd *fd, int allow_synchronous_callback) { - set_ready(fd, &fd->readst, allow_synchronous_callback); -} - -void grpc_fd_become_writable(grpc_fd *fd, int allow_synchronous_callback) { - set_ready(fd, &fd->writest, allow_synchronous_callback); -} diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h deleted file mode 100644 index 232de0c3e08..00000000000 --- a/src/core/iomgr/fd_posix.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GRPC_INTERNAL_IOMGR_FD_POSIX_H_ -#define __GRPC_INTERNAL_IOMGR_FD_POSIX_H_ - -#include "src/core/iomgr/iomgr.h" -#include "src/core/iomgr/pollset.h" -#include -#include -#include - -typedef struct { - grpc_iomgr_cb_func cb; - void *cb_arg; - int success; - gpr_atm state; -} grpc_fd_state; - -typedef struct grpc_fd { - int fd; - /* refst format: - bit0: 1=active/0=orphaned - bit1-n: refcount - meaning that mostly we ref by two to avoid altering the orphaned bit, - and just unref by 1 when we're ready to flag the object as orphaned */ - gpr_atm refst; - - gpr_mu set_state_mu; - gpr_atm shutdown; - - gpr_mu watcher_mu; - grpc_pollset **watchers; - size_t watcher_count; - size_t watcher_capacity; - - grpc_fd_state readst; - grpc_fd_state writest; - - grpc_iomgr_cb_func on_done; - void *on_done_user_data; -} grpc_fd; - -/* Create a wrapped file descriptor. - Requires fd is a non-blocking file descriptor. - This takes ownership of closing fd. */ -grpc_fd *grpc_fd_create(int fd); - -/* Releases fd to be asynchronously destroyed. - on_done is called when the underlying file descriptor is definitely close()d. - If on_done is NULL, no callback will be made. - Requires: *fd initialized; no outstanding notify_on_read or - notify_on_write. */ -void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data); - -/* Begin polling on an fd. - Registers that the given pollset is interested in this fd - so that if read - or writability interest changes, the pollset can be kicked to pick up that - new interest. - Return value is: - (fd_needs_read? read_mask : 0) | (fd_needs_write? write_mask : 0) - i.e. a combination of read_mask and write_mask determined by the fd's current - interest in said events. - Polling strategies that do not need to alter their behavior depending on the - fd's current interest (such as epoll) do not need to call this function. */ -gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, - gpr_uint32 read_mask, gpr_uint32 write_mask); -/* Complete polling previously started with grpc_fd_begin_poll */ -void grpc_fd_end_poll(grpc_fd *fd, grpc_pollset *pollset); - -/* Return 1 if this fd is orphaned, 0 otherwise */ -int grpc_fd_is_orphaned(grpc_fd *fd); - -/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */ -void grpc_fd_shutdown(grpc_fd *fd); - -/* Register read interest, causing read_cb to be called once when fd becomes - readable, on deadline specified by deadline, or on shutdown triggered by - grpc_fd_shutdown. - read_cb will be called with read_cb_arg when *fd becomes readable. - read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable, - GRPC_CALLBACK_TIMED_OUT if the call timed out, - and CANCELLED if the call was cancelled. - - Requires:This method must not be called before the read_cb for any previous - call runs. Edge triggered events are used whenever they are supported by the - underlying platform. This means that users must drain fd in read_cb before - calling notify_on_read again. Users are also expected to handle spurious - events, i.e read_cb is called while nothing can be readable from fd */ -void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_cb_func read_cb, - void *read_cb_arg); - -/* Exactly the same semantics as above, except based on writable events. */ -void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, - void *write_cb_arg); - -/* Notification from the poller to an fd that it has become readable or - writable. - If allow_synchronous_callback is 1, allow running the fd callback inline - in this callstack, otherwise register an asynchronous callback and return */ -void grpc_fd_become_readable(grpc_fd *fd, int allow_synchronous_callback); -void grpc_fd_become_writable(grpc_fd *fd, int allow_synchronous_callback); - -/* Reference counting for fds */ -void grpc_fd_ref(grpc_fd *fd); -void grpc_fd_unref(grpc_fd *fd); - -#endif /* __GRPC_INTERNAL_IOMGR_FD_POSIX_H_ */ diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c deleted file mode 100644 index 03f56a50a32..00000000000 --- a/src/core/iomgr/iomgr.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/iomgr.h" - -#include - -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/alarm_internal.h" -#include -#include -#include -#include - -typedef struct delayed_callback { - grpc_iomgr_cb_func cb; - void *cb_arg; - int success; - struct delayed_callback *next; -} delayed_callback; - -static gpr_mu g_mu; -static gpr_cv g_cv; -static delayed_callback *g_cbs_head = NULL; -static delayed_callback *g_cbs_tail = NULL; -static int g_shutdown; -static int g_refs; -static gpr_event g_background_callback_executor_done; - -/* Execute followup callbacks continuously. - Other threads may check in and help during pollset_work() */ -static void background_callback_executor(void *ignored) { - gpr_mu_lock(&g_mu); - while (!g_shutdown) { - gpr_timespec deadline = gpr_inf_future; - if (g_cbs_head) { - delayed_callback *cb = g_cbs_head; - g_cbs_head = cb->next; - if (!g_cbs_head) g_cbs_tail = NULL; - gpr_mu_unlock(&g_mu); - cb->cb(cb->cb_arg, cb->success); - gpr_free(cb); - gpr_mu_lock(&g_mu); - } else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) { - } else { - gpr_cv_wait(&g_cv, &g_mu, deadline); - } - } - gpr_mu_unlock(&g_mu); - gpr_event_set(&g_background_callback_executor_done, (void *)1); -} - -void grpc_kick_poller() { gpr_cv_broadcast(&g_cv); } - -void grpc_iomgr_init() { - gpr_thd_id id; - gpr_mu_init(&g_mu); - gpr_cv_init(&g_cv); - grpc_alarm_list_init(gpr_now()); - g_refs = 0; - grpc_iomgr_platform_init(); - gpr_event_init(&g_background_callback_executor_done); - gpr_thd_new(&id, background_callback_executor, NULL, NULL); -} - -void grpc_iomgr_shutdown() { - delayed_callback *cb; - gpr_timespec shutdown_deadline = - gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); - - grpc_iomgr_platform_shutdown(); - - gpr_mu_lock(&g_mu); - g_shutdown = 1; - while (g_cbs_head || g_refs) { - gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs, - g_cbs_head ? " and executing final callbacks" : ""); - while (g_cbs_head) { - cb = g_cbs_head; - g_cbs_head = cb->next; - if (!g_cbs_head) g_cbs_tail = NULL; - gpr_mu_unlock(&g_mu); - - cb->cb(cb->cb_arg, 0); - gpr_free(cb); - gpr_mu_lock(&g_mu); - } - if (g_refs) { - if (gpr_cv_wait(&g_cv, &g_mu, shutdown_deadline) && g_cbs_head == NULL) { - gpr_log(GPR_DEBUG, - "Failed to free %d iomgr objects before shutdown deadline: " - "memory leaks are likely", - g_refs); - break; - } - } - } - gpr_mu_unlock(&g_mu); - - gpr_event_wait(&g_background_callback_executor_done, gpr_inf_future); - - grpc_alarm_list_shutdown(); - gpr_mu_destroy(&g_mu); - gpr_cv_destroy(&g_cv); -} - -void grpc_iomgr_ref() { - gpr_mu_lock(&g_mu); - ++g_refs; - gpr_mu_unlock(&g_mu); -} - -void grpc_iomgr_unref() { - gpr_mu_lock(&g_mu); - if (0 == --g_refs) { - gpr_cv_signal(&g_cv); - } - gpr_mu_unlock(&g_mu); -} - -void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg, - int success) { - delayed_callback *dcb = gpr_malloc(sizeof(delayed_callback)); - dcb->cb = cb; - dcb->cb_arg = cb_arg; - dcb->success = success; - gpr_mu_lock(&g_mu); - dcb->next = NULL; - if (!g_cbs_tail) { - g_cbs_head = g_cbs_tail = dcb; - } else { - g_cbs_tail->next = dcb; - g_cbs_tail = dcb; - } - gpr_cv_signal(&g_cv); - gpr_mu_unlock(&g_mu); -} - -void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg) { - grpc_iomgr_add_delayed_callback(cb, cb_arg, 1); -} - -int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) { - int n = 0; - gpr_mu *retake_mu = NULL; - delayed_callback *cb; - for (;;) { - /* check for new work */ - if (!gpr_mu_trylock(&g_mu)) { - break; - } - cb = g_cbs_head; - if (!cb) { - gpr_mu_unlock(&g_mu); - break; - } - g_cbs_head = cb->next; - if (!g_cbs_head) g_cbs_tail = NULL; - gpr_mu_unlock(&g_mu); - /* if we have a mutex to drop, do so before executing work */ - if (drop_mu) { - gpr_mu_unlock(drop_mu); - retake_mu = drop_mu; - drop_mu = NULL; - } - cb->cb(cb->cb_arg, success && cb->success); - gpr_free(cb); - n++; - } - if (retake_mu) { - gpr_mu_lock(retake_mu); - } - return n; -} diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h index 16991a9b90e..cf39f947bc2 100644 --- a/src/core/iomgr/iomgr.h +++ b/src/core/iomgr/iomgr.h @@ -34,8 +34,17 @@ #ifndef __GRPC_INTERNAL_IOMGR_IOMGR_H__ #define __GRPC_INTERNAL_IOMGR_IOMGR_H__ +/* Status passed to callbacks for grpc_em_fd_notify_on_read and + grpc_em_fd_notify_on_write. */ +typedef enum grpc_em_cb_status { + GRPC_CALLBACK_SUCCESS = 0, + GRPC_CALLBACK_TIMED_OUT, + GRPC_CALLBACK_CANCELLED, + GRPC_CALLBACK_DO_NOT_USE +} grpc_iomgr_cb_status; + /* gRPC Callback definition */ -typedef void (*grpc_iomgr_cb_func)(void *arg, int success); +typedef void (*grpc_iomgr_cb_func)(void *arg, grpc_iomgr_cb_status status); void grpc_iomgr_init(); void grpc_iomgr_shutdown(); diff --git a/src/core/iomgr/iomgr_posix.h b/src/core/iomgr/iomgr_completion_queue_interface.h similarity index 79% rename from src/core/iomgr/iomgr_posix.h rename to src/core/iomgr/iomgr_completion_queue_interface.h index ca5af3e5276..3c4efe773a7 100644 --- a/src/core/iomgr/iomgr_posix.h +++ b/src/core/iomgr/iomgr_completion_queue_interface.h @@ -31,12 +31,15 @@ * */ -#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_POSIX_H_ -#define __GRPC_INTERNAL_IOMGR_IOMGR_POSIX_H_ +#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_COMPLETION_QUEUE_INTERFACE_H_ +#define __GRPC_INTERNAL_IOMGR_IOMGR_COMPLETION_QUEUE_INTERFACE_H_ -#include "src/core/iomgr/iomgr_internal.h" +/* Internals of iomgr that are exposed only to be used for completion queue + implementation */ -void grpc_pollset_global_init(); -void grpc_pollset_global_shutdown(); +extern gpr_mu grpc_iomgr_mu; +extern gpr_cv grpc_iomgr_cv; -#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_POSIX_H_ */ +int grpc_iomgr_work(gpr_timespec deadline); + +#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_COMPLETION_QUEUE_INTERFACE_H_ */ diff --git a/src/core/iomgr/iomgr_libevent.c b/src/core/iomgr/iomgr_libevent.c new file mode 100644 index 00000000000..6188ab2749c --- /dev/null +++ b/src/core/iomgr/iomgr_libevent.c @@ -0,0 +1,652 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/iomgr/iomgr_libevent.h" + +#include +#include + +#include "src/core/iomgr/alarm.h" +#include "src/core/iomgr/alarm_internal.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define ALARM_TRIGGER_INIT ((gpr_atm)0) +#define ALARM_TRIGGER_INCREMENT ((gpr_atm)1) +#define DONE_SHUTDOWN ((void *)1) + +#define POLLER_ID_INVALID ((gpr_atm)-1) + +/* Global data */ +struct event_base *g_event_base; +gpr_mu grpc_iomgr_mu; +gpr_cv grpc_iomgr_cv; +static grpc_libevent_activation_data *g_activation_queue; +static int g_num_pollers; +static int g_num_fds; +static int g_num_address_resolutions; +static gpr_timespec g_last_poll_completed; +static int g_shutdown_backup_poller; +static gpr_event g_backup_poller_done; +/* activated to break out of the event loop early */ +static struct event *g_timeout_ev; +/* activated to safely break polling from other threads */ +static struct event *g_break_ev; +static grpc_fd *g_fds_to_free; + +int evthread_use_threads(void); +static void grpc_fd_impl_destroy(grpc_fd *impl); + +void grpc_iomgr_ref_address_resolution(int delta) { + gpr_mu_lock(&grpc_iomgr_mu); + GPR_ASSERT(!g_shutdown_backup_poller); + g_num_address_resolutions += delta; + if (0 == g_num_address_resolutions) { + gpr_cv_broadcast(&grpc_iomgr_cv); + } + gpr_mu_unlock(&grpc_iomgr_mu); +} + +/* If anything is in the work queue, process one item and return 1. + Return 0 if there were no work items to complete. + Requires grpc_iomgr_mu locked, may unlock and relock during the call. */ +static int maybe_do_queue_work() { + grpc_libevent_activation_data *work = g_activation_queue; + + if (work == NULL) return 0; + + if (work->next == work) { + g_activation_queue = NULL; + } else { + g_activation_queue = work->next; + g_activation_queue->prev = work->prev; + g_activation_queue->next->prev = g_activation_queue->prev->next = + g_activation_queue; + } + work->next = work->prev = NULL; + /* force status to cancelled from ok when shutting down */ + if (g_shutdown_backup_poller && work->status == GRPC_CALLBACK_SUCCESS) { + work->status = GRPC_CALLBACK_CANCELLED; + } + gpr_mu_unlock(&grpc_iomgr_mu); + + work->cb(work->arg, work->status); + + gpr_mu_lock(&grpc_iomgr_mu); + return 1; +} + +/* Break out of the event loop on timeout */ +static void timer_callback(int fd, short events, void *context) { + event_base_loopbreak((struct event_base *)context); +} + +static void break_callback(int fd, short events, void *context) { + event_base_loopbreak((struct event_base *)context); +} + +static void free_fd_list(grpc_fd *impl) { + while (impl != NULL) { + grpc_fd *current = impl; + impl = impl->next; + grpc_fd_impl_destroy(current); + current->on_done(current->on_done_user_data, GRPC_CALLBACK_SUCCESS); + gpr_free(current); + } +} + +static void maybe_free_fds() { + if (g_fds_to_free) { + free_fd_list(g_fds_to_free); + g_fds_to_free = NULL; + } +} + +void grpc_kick_poller() { event_active(g_break_ev, EV_READ, 0); } + +/* Spend some time doing polling and libevent maintenance work if no other + thread is. This includes both polling for events and destroying/closing file + descriptor objects. + Returns 1 if polling was performed, 0 otherwise. + Requires grpc_iomgr_mu locked, may unlock and relock during the call. */ +static int maybe_do_polling_work(struct timeval delay) { + int status; + + if (g_num_pollers) return 0; + + g_num_pollers = 1; + + maybe_free_fds(); + + gpr_mu_unlock(&grpc_iomgr_mu); + + event_add(g_timeout_ev, &delay); + status = event_base_loop(g_event_base, EVLOOP_ONCE); + if (status < 0) { + gpr_log(GPR_ERROR, "event polling loop stops with error status %d", status); + } + event_del(g_timeout_ev); + + gpr_mu_lock(&grpc_iomgr_mu); + maybe_free_fds(); + + g_num_pollers = 0; + gpr_cv_broadcast(&grpc_iomgr_cv); + return 1; +} + +static int maybe_do_alarm_work(gpr_timespec now, gpr_timespec next) { + int r = 0; + if (gpr_time_cmp(next, now) < 0) { + gpr_mu_unlock(&grpc_iomgr_mu); + r = grpc_alarm_check(now); + gpr_mu_lock(&grpc_iomgr_mu); + } + return r; +} + +int grpc_iomgr_work(gpr_timespec deadline) { + gpr_timespec now = gpr_now(); + gpr_timespec next = grpc_alarm_list_next_timeout(); + gpr_timespec delay_timespec = gpr_time_sub(deadline, now); + /* poll for no longer than one second */ + gpr_timespec max_delay = gpr_time_from_seconds(1); + struct timeval delay; + + if (gpr_time_cmp(delay_timespec, gpr_time_0) <= 0) { + return 0; + } + + if (gpr_time_cmp(delay_timespec, max_delay) > 0) { + delay_timespec = max_delay; + } + + /* Adjust delay to account for the next alarm, if applicable. */ + delay_timespec = gpr_time_min( + delay_timespec, gpr_time_sub(grpc_alarm_list_next_timeout(), now)); + + delay = gpr_timeval_from_timespec(delay_timespec); + + if (maybe_do_queue_work() || maybe_do_alarm_work(now, next) || + maybe_do_polling_work(delay)) { + g_last_poll_completed = gpr_now(); + return 1; + } + + return 0; +} + +static void backup_poller_thread(void *p) { + int backup_poller_engaged = 0; + /* allow no pollers for 100 milliseconds, then engage backup polling */ + gpr_timespec allow_no_pollers = gpr_time_from_millis(100); + + gpr_mu_lock(&grpc_iomgr_mu); + while (!g_shutdown_backup_poller) { + if (g_num_pollers == 0) { + gpr_timespec now = gpr_now(); + gpr_timespec time_until_engage = gpr_time_sub( + allow_no_pollers, gpr_time_sub(now, g_last_poll_completed)); + if (gpr_time_cmp(time_until_engage, gpr_time_0) <= 0) { + if (!backup_poller_engaged) { + gpr_log(GPR_DEBUG, "No pollers for a while - engaging backup poller"); + backup_poller_engaged = 1; + } + if (!maybe_do_queue_work()) { + gpr_timespec next = grpc_alarm_list_next_timeout(); + if (!maybe_do_alarm_work(now, next)) { + gpr_timespec deadline = + gpr_time_min(next, gpr_time_add(now, gpr_time_from_seconds(1))); + maybe_do_polling_work( + gpr_timeval_from_timespec(gpr_time_sub(deadline, now))); + } + } + } else { + if (backup_poller_engaged) { + gpr_log(GPR_DEBUG, "Backup poller disengaged"); + backup_poller_engaged = 0; + } + gpr_mu_unlock(&grpc_iomgr_mu); + gpr_sleep_until(gpr_time_add(now, time_until_engage)); + gpr_mu_lock(&grpc_iomgr_mu); + } + } else { + if (backup_poller_engaged) { + gpr_log(GPR_DEBUG, "Backup poller disengaged"); + backup_poller_engaged = 0; + } + gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, gpr_inf_future); + } + } + gpr_mu_unlock(&grpc_iomgr_mu); + + gpr_event_set(&g_backup_poller_done, (void *)1); +} + +void grpc_iomgr_init() { + gpr_thd_id backup_poller_id; + + if (evthread_use_threads() != 0) { + gpr_log(GPR_ERROR, "Failed to initialize libevent thread support!"); + abort(); + } + + grpc_alarm_list_init(gpr_now()); + + gpr_mu_init(&grpc_iomgr_mu); + gpr_cv_init(&grpc_iomgr_cv); + g_activation_queue = NULL; + g_num_pollers = 0; + g_num_fds = 0; + g_num_address_resolutions = 0; + g_last_poll_completed = gpr_now(); + g_shutdown_backup_poller = 0; + g_fds_to_free = NULL; + + gpr_event_init(&g_backup_poller_done); + + g_event_base = NULL; + g_timeout_ev = NULL; + g_break_ev = NULL; + + g_event_base = event_base_new(); + if (!g_event_base) { + gpr_log(GPR_ERROR, "Failed to create the event base"); + abort(); + } + + if (evthread_make_base_notifiable(g_event_base) != 0) { + gpr_log(GPR_ERROR, "Couldn't make event base notifiable cross threads!"); + abort(); + } + + g_timeout_ev = evtimer_new(g_event_base, timer_callback, g_event_base); + g_break_ev = event_new(g_event_base, -1, EV_READ | EV_PERSIST, break_callback, + g_event_base); + + event_add(g_break_ev, NULL); + + gpr_thd_new(&backup_poller_id, backup_poller_thread, NULL, NULL); +} + +void grpc_iomgr_shutdown() { + gpr_timespec fd_shutdown_deadline = + gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); + + /* broadcast shutdown */ + gpr_mu_lock(&grpc_iomgr_mu); + while (g_num_fds > 0 || g_num_address_resolutions > 0) { + gpr_log(GPR_INFO, + "waiting for %d fds and %d name resolutions to be destroyed before " + "closing event manager", + g_num_fds, g_num_address_resolutions); + if (gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, fd_shutdown_deadline)) { + gpr_log(GPR_ERROR, + "not all fds or name resolutions destroyed before shutdown " + "deadline: memory leaks " + "are likely"); + break; + } else if (g_num_fds == 0 && g_num_address_resolutions == 0) { + gpr_log(GPR_INFO, "all fds closed, all name resolutions finished"); + } + } + + g_shutdown_backup_poller = 1; + gpr_cv_broadcast(&grpc_iomgr_cv); + gpr_mu_unlock(&grpc_iomgr_mu); + + gpr_event_wait(&g_backup_poller_done, gpr_inf_future); + + grpc_alarm_list_shutdown(); + + /* drain pending work */ + gpr_mu_lock(&grpc_iomgr_mu); + while (maybe_do_queue_work()) + ; + gpr_mu_unlock(&grpc_iomgr_mu); + + free_fd_list(g_fds_to_free); + + /* complete shutdown */ + gpr_mu_destroy(&grpc_iomgr_mu); + gpr_cv_destroy(&grpc_iomgr_cv); + + if (g_timeout_ev != NULL) { + event_free(g_timeout_ev); + } + + if (g_break_ev != NULL) { + event_free(g_break_ev); + } + + if (g_event_base != NULL) { + event_base_free(g_event_base); + g_event_base = NULL; + } +} + +static void add_task(grpc_libevent_activation_data *adata) { + gpr_mu_lock(&grpc_iomgr_mu); + if (g_activation_queue) { + adata->next = g_activation_queue; + adata->prev = adata->next->prev; + adata->next->prev = adata->prev->next = adata; + } else { + g_activation_queue = adata; + adata->next = adata->prev = adata; + } + gpr_cv_broadcast(&grpc_iomgr_cv); + gpr_mu_unlock(&grpc_iomgr_mu); +} + +static void grpc_fd_impl_destroy(grpc_fd *impl) { + grpc_em_task_activity_type type; + grpc_libevent_activation_data *adata; + + for (type = GRPC_EM_TA_READ; type < GRPC_EM_TA_COUNT; type++) { + adata = &(impl->task.activation[type]); + GPR_ASSERT(adata->next == NULL); + if (adata->ev != NULL) { + event_free(adata->ev); + adata->ev = NULL; + } + } + + if (impl->shutdown_ev != NULL) { + event_free(impl->shutdown_ev); + impl->shutdown_ev = NULL; + } + gpr_mu_destroy(&impl->mu); + close(impl->fd); +} + +/* Proxy callback to call a gRPC read/write callback */ +static void em_fd_cb(int fd, short what, void *arg /*=em_fd*/) { + grpc_fd *em_fd = arg; + grpc_iomgr_cb_status status = GRPC_CALLBACK_SUCCESS; + int run_read_cb = 0; + int run_write_cb = 0; + grpc_libevent_activation_data *rdata, *wdata; + + gpr_mu_lock(&em_fd->mu); + if (em_fd->shutdown_started) { + status = GRPC_CALLBACK_CANCELLED; + } else if (status == GRPC_CALLBACK_SUCCESS && (what & EV_TIMEOUT)) { + status = GRPC_CALLBACK_TIMED_OUT; + /* TODO(klempner): This is broken if we are monitoring both read and write + events on the same fd -- generating a spurious event is okay, but + generating a spurious timeout is not. */ + what |= (EV_READ | EV_WRITE); + } + + if (what & EV_READ) { + switch (em_fd->read_state) { + case GRPC_FD_WAITING: + run_read_cb = 1; + em_fd->read_state = GRPC_FD_IDLE; + break; + case GRPC_FD_IDLE: + case GRPC_FD_CACHED: + em_fd->read_state = GRPC_FD_CACHED; + } + } + if (what & EV_WRITE) { + switch (em_fd->write_state) { + case GRPC_FD_WAITING: + run_write_cb = 1; + em_fd->write_state = GRPC_FD_IDLE; + break; + case GRPC_FD_IDLE: + case GRPC_FD_CACHED: + em_fd->write_state = GRPC_FD_CACHED; + } + } + + if (run_read_cb) { + rdata = &(em_fd->task.activation[GRPC_EM_TA_READ]); + rdata->status = status; + add_task(rdata); + } else if (run_write_cb) { + wdata = &(em_fd->task.activation[GRPC_EM_TA_WRITE]); + wdata->status = status; + add_task(wdata); + } + gpr_mu_unlock(&em_fd->mu); +} + +static void em_fd_shutdown_cb(int fd, short what, void *arg /*=em_fd*/) { + /* TODO(klempner): This could just run directly in the calling thread, except + that libevent's handling of event_active() on an event which is already in + flight on a different thread is racy and easily triggers TSAN. + */ + grpc_fd *impl = arg; + gpr_mu_lock(&impl->mu); + impl->shutdown_started = 1; + if (impl->read_state == GRPC_FD_WAITING) { + event_active(impl->task.activation[GRPC_EM_TA_READ].ev, EV_READ, 1); + } + if (impl->write_state == GRPC_FD_WAITING) { + event_active(impl->task.activation[GRPC_EM_TA_WRITE].ev, EV_WRITE, 1); + } + gpr_mu_unlock(&impl->mu); +} + +grpc_fd *grpc_fd_create(int fd) { + int flags; + grpc_libevent_activation_data *rdata, *wdata; + grpc_fd *impl = gpr_malloc(sizeof(grpc_fd)); + + gpr_mu_lock(&grpc_iomgr_mu); + g_num_fds++; + gpr_mu_unlock(&grpc_iomgr_mu); + + impl->shutdown_ev = NULL; + gpr_mu_init(&impl->mu); + + flags = fcntl(fd, F_GETFL, 0); + GPR_ASSERT((flags & O_NONBLOCK) != 0); + + impl->task.type = GRPC_EM_TASK_FD; + impl->fd = fd; + + rdata = &(impl->task.activation[GRPC_EM_TA_READ]); + rdata->ev = NULL; + rdata->cb = NULL; + rdata->arg = NULL; + rdata->status = GRPC_CALLBACK_SUCCESS; + rdata->prev = NULL; + rdata->next = NULL; + + wdata = &(impl->task.activation[GRPC_EM_TA_WRITE]); + wdata->ev = NULL; + wdata->cb = NULL; + wdata->arg = NULL; + wdata->status = GRPC_CALLBACK_SUCCESS; + wdata->prev = NULL; + wdata->next = NULL; + + impl->read_state = GRPC_FD_IDLE; + impl->write_state = GRPC_FD_IDLE; + + impl->shutdown_started = 0; + impl->next = NULL; + + /* TODO(chenw): detect platforms where only level trigger is supported, + and set the event to non-persist. */ + rdata->ev = event_new(g_event_base, impl->fd, EV_ET | EV_PERSIST | EV_READ, + em_fd_cb, impl); + GPR_ASSERT(rdata->ev); + + wdata->ev = event_new(g_event_base, impl->fd, EV_ET | EV_PERSIST | EV_WRITE, + em_fd_cb, impl); + GPR_ASSERT(wdata->ev); + + impl->shutdown_ev = + event_new(g_event_base, -1, EV_READ, em_fd_shutdown_cb, impl); + GPR_ASSERT(impl->shutdown_ev); + + return impl; +} + +static void do_nothing(void *ignored, grpc_iomgr_cb_status also_ignored) {} + +void grpc_fd_destroy(grpc_fd *impl, grpc_iomgr_cb_func on_done, + void *user_data) { + if (on_done == NULL) on_done = do_nothing; + + gpr_mu_lock(&grpc_iomgr_mu); + + /* Put the impl on the list to be destroyed by the poller. */ + impl->on_done = on_done; + impl->on_done_user_data = user_data; + impl->next = g_fds_to_free; + g_fds_to_free = impl; + /* TODO(ctiller): kick the poller so it destroys this fd promptly + (currently we may wait up to a second) */ + + g_num_fds--; + gpr_cv_broadcast(&grpc_iomgr_cv); + gpr_mu_unlock(&grpc_iomgr_mu); +} + +int grpc_fd_get(struct grpc_fd *em_fd) { return em_fd->fd; } + +/* TODO(chenw): should we enforce the contract that notify_on_read cannot be + called when the previously registered callback has not been called yet. */ +int grpc_fd_notify_on_read(grpc_fd *impl, grpc_iomgr_cb_func read_cb, + void *read_cb_arg, gpr_timespec deadline) { + int force_event = 0; + grpc_libevent_activation_data *rdata; + gpr_timespec delay_timespec = gpr_time_sub(deadline, gpr_now()); + struct timeval delay = gpr_timeval_from_timespec(delay_timespec); + struct timeval *delayp = + gpr_time_cmp(deadline, gpr_inf_future) ? &delay : NULL; + + rdata = &impl->task.activation[GRPC_EM_TA_READ]; + + gpr_mu_lock(&impl->mu); + rdata->cb = read_cb; + rdata->arg = read_cb_arg; + + force_event = (impl->shutdown_started || impl->read_state == GRPC_FD_CACHED); + impl->read_state = GRPC_FD_WAITING; + + if (force_event) { + event_active(rdata->ev, EV_READ, 1); + } else if (event_add(rdata->ev, delayp) == -1) { + gpr_mu_unlock(&impl->mu); + return 0; + } + gpr_mu_unlock(&impl->mu); + return 1; +} + +int grpc_fd_notify_on_write(grpc_fd *impl, grpc_iomgr_cb_func write_cb, + void *write_cb_arg, gpr_timespec deadline) { + int force_event = 0; + grpc_libevent_activation_data *wdata; + gpr_timespec delay_timespec = gpr_time_sub(deadline, gpr_now()); + struct timeval delay = gpr_timeval_from_timespec(delay_timespec); + struct timeval *delayp = + gpr_time_cmp(deadline, gpr_inf_future) ? &delay : NULL; + + wdata = &impl->task.activation[GRPC_EM_TA_WRITE]; + + gpr_mu_lock(&impl->mu); + wdata->cb = write_cb; + wdata->arg = write_cb_arg; + + force_event = (impl->shutdown_started || impl->write_state == GRPC_FD_CACHED); + impl->write_state = GRPC_FD_WAITING; + + if (force_event) { + event_active(wdata->ev, EV_WRITE, 1); + } else if (event_add(wdata->ev, delayp) == -1) { + gpr_mu_unlock(&impl->mu); + return 0; + } + gpr_mu_unlock(&impl->mu); + return 1; +} + +void grpc_fd_shutdown(grpc_fd *em_fd) { + event_active(em_fd->shutdown_ev, EV_READ, 1); +} + +/* Sometimes we want a followup callback: something to be added from the + current callback for the EM to invoke once this callback is complete. + This is implemented by inserting an entry into an EM queue. */ + +/* The following structure holds the field needed for adding the + followup callback. These are the argument for the followup callback, + the function to use for the followup callback, and the + activation data pointer used for the queues (to free in the CB) */ +struct followup_callback_arg { + grpc_iomgr_cb_func func; + void *cb_arg; + grpc_libevent_activation_data adata; +}; + +static void followup_proxy_callback(void *cb_arg, grpc_iomgr_cb_status status) { + struct followup_callback_arg *fcb_arg = cb_arg; + /* Invoke the function */ + fcb_arg->func(fcb_arg->cb_arg, status); + gpr_free(fcb_arg); +} + +void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg) { + grpc_libevent_activation_data *adptr; + struct followup_callback_arg *fcb_arg; + + fcb_arg = gpr_malloc(sizeof(*fcb_arg)); + /* Set up the activation data and followup callback argument structures */ + adptr = &fcb_arg->adata; + adptr->ev = NULL; + adptr->cb = followup_proxy_callback; + adptr->arg = fcb_arg; + adptr->status = GRPC_CALLBACK_SUCCESS; + adptr->prev = NULL; + adptr->next = NULL; + + fcb_arg->func = cb; + fcb_arg->cb_arg = cb_arg; + + /* Insert an activation data for the specified em */ + add_task(adptr); +} diff --git a/src/core/iomgr/iomgr_libevent.h b/src/core/iomgr/iomgr_libevent.h new file mode 100644 index 00000000000..5c088006a0a --- /dev/null +++ b/src/core/iomgr/iomgr_libevent.h @@ -0,0 +1,206 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_LIBEVENT_H__ +#define __GRPC_INTERNAL_IOMGR_IOMGR_LIBEVENT_H__ + +#include "src/core/iomgr/iomgr.h" +#include +#include + +typedef struct grpc_fd grpc_fd; + +/* gRPC event manager task "base class". This is pretend-inheritance in C89. + This should be the first member of any actual grpc_em task type. + + Memory warning: expanding this will increase memory usage in any derived + class, so be careful. + + For generality, this base can be on multiple task queues and can have + multiple event callbacks registered. Not all "derived classes" will use + this feature. */ + +typedef enum grpc_libevent_task_type { + GRPC_EM_TASK_ALARM, + GRPC_EM_TASK_FD, + GRPC_EM_TASK_DO_NOT_USE +} grpc_libevent_task_type; + +/* Different activity types to shape the callback and queueing arrays */ +typedef enum grpc_em_task_activity_type { + GRPC_EM_TA_READ, /* use this also for single-type events */ + GRPC_EM_TA_WRITE, + GRPC_EM_TA_COUNT +} grpc_em_task_activity_type; + +/* Include the following #define for convenience for tasks like alarms that + only have a single type */ +#define GRPC_EM_TA_ONLY GRPC_EM_TA_READ + +typedef struct grpc_libevent_activation_data { + struct event *ev; /* event activated on this callback type */ + grpc_iomgr_cb_func cb; /* function pointer for callback */ + void *arg; /* argument passed to cb */ + + /* Hold the status associated with the callback when queued */ + grpc_iomgr_cb_status status; + /* Now set up to link activations into scheduler queues */ + struct grpc_libevent_activation_data *prev; + struct grpc_libevent_activation_data *next; +} grpc_libevent_activation_data; + +typedef struct grpc_libevent_task { + grpc_libevent_task_type type; + + /* Now have an array of activation data elements: one for each activity + type that could get activated */ + grpc_libevent_activation_data activation[GRPC_EM_TA_COUNT]; +} grpc_libevent_task; + +/* Initialize *em_fd. + Requires fd is a non-blocking file descriptor. + + This takes ownership of closing fd. + + Requires: *em_fd uninitialized. fd is a non-blocking file descriptor. */ +grpc_fd *grpc_fd_create(int fd); + +/* Cause *em_fd no longer to be initialized and closes the underlying fd. + on_done is called when the underlying file descriptor is definitely close()d. + If on_done is NULL, no callback will be made. + Requires: *em_fd initialized; no outstanding notify_on_read or + notify_on_write. */ +void grpc_fd_destroy(grpc_fd *em_fd, grpc_iomgr_cb_func on_done, + void *user_data); + +/* Returns the file descriptor associated with *em_fd. */ +int grpc_fd_get(grpc_fd *em_fd); + +/* Register read interest, causing read_cb to be called once when em_fd becomes + readable, on deadline specified by deadline, or on shutdown triggered by + grpc_fd_shutdown. + read_cb will be called with read_cb_arg when *em_fd becomes readable. + read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable, + GRPC_CALLBACK_TIMED_OUT if the call timed out, + and CANCELLED if the call was cancelled. + + Requires:This method must not be called before the read_cb for any previous + call runs. Edge triggered events are used whenever they are supported by the + underlying platform. This means that users must drain em_fd in read_cb before + calling notify_on_read again. Users are also expected to handle spurious + events, i.e read_cb is called while nothing can be readable from em_fd */ +int grpc_fd_notify_on_read(grpc_fd *em_fd, grpc_iomgr_cb_func read_cb, + void *read_cb_arg, gpr_timespec deadline); + +/* Exactly the same semantics as above, except based on writable events. */ +int grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, + void *write_cb_arg, gpr_timespec deadline); + +/* Cause any current and all future read/write callbacks to error out with + GRPC_CALLBACK_CANCELLED. */ +void grpc_fd_shutdown(grpc_fd *em_fd); + +/* =================== Event caching =================== + In order to not miss or double-return edges in the context of edge triggering + and multithreading, we need a per-fd caching layer in the eventmanager itself + to cache relevant events. + + There are two types of events we care about: calls to notify_on_[read|write] + and readable/writable events for the socket from eventfd. There are separate + event caches for read and write. + + There are three states: + 0. "waiting" -- There's been a call to notify_on_[read|write] which has not + had a corresponding event. In other words, we're waiting for an event so we + can run the callback. + 1. "idle" -- We are neither waiting nor have a cached event. + 2. "cached" -- There has been a read/write event without a waiting callback, + so we want to run the event next time the application calls + notify_on_[read|write]. + + The high level state diagram: + + +--------------------------------------------------------------------+ + | WAITING | IDLE | CACHED | + | | | | + | 1. --*-> 2. --+-> 3. --+\ + | | | <--+/ + | | | | + x+-- 6. 5. <-+-- 4. <-*-- | + | | | | + +--------------------------------------------------------------------+ + + Transitions right occur on read|write events. Transitions left occur on + notify_on_[read|write] events. + State transitions: + 1. Read|Write event while waiting -> run the callback and transition to idle. + 2. Read|Write event while idle -> transition to cached. + 3. Read|Write event with one already cached -> still cached. + 4. notify_on_[read|write] with event cached: run callback and transition to + idle. + 5. notify_on_[read|write] when idle: Store callback and transition to + waiting. + 6. notify_on_[read|write] when waiting: invalid. */ + +typedef enum grpc_fd_state { + GRPC_FD_WAITING = 0, + GRPC_FD_IDLE = 1, + GRPC_FD_CACHED = 2 +} grpc_fd_state; + +/* gRPC file descriptor handle. + The handle is used to register read/write callbacks to a file descriptor */ +struct grpc_fd { + grpc_libevent_task task; /* Base class, callbacks, queues, etc */ + int fd; /* File descriptor */ + + /* Note that the shutdown event is only needed as a workaround for libevent + not properly handling event_active on an in flight event. */ + struct event *shutdown_ev; /* activated to trigger shutdown */ + + /* protect shutdown_started|read_state|write_state and ensure barriers + between notify_on_[read|write] and read|write callbacks */ + gpr_mu mu; + int shutdown_started; /* 0 -> shutdown not started, 1 -> started */ + grpc_fd_state read_state; + grpc_fd_state write_state; + + /* descriptor delete list. These are destroyed during polling. */ + struct grpc_fd *next; + grpc_iomgr_cb_func on_done; + void *on_done_user_data; +}; + +void grpc_iomgr_ref_address_resolution(int delta); + +#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_LIBEVENT_H__ */ diff --git a/src/core/iomgr/iomgr_internal.h b/src/core/iomgr/iomgr_libevent_use_threads.c similarity index 67% rename from src/core/iomgr/iomgr_internal.h rename to src/core/iomgr/iomgr_libevent_use_threads.c index 5f72542777d..af449342f0c 100644 --- a/src/core/iomgr/iomgr_internal.h +++ b/src/core/iomgr/iomgr_libevent_use_threads.c @@ -31,21 +31,26 @@ * */ -#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_INTERNAL_H_ -#define __GRPC_INTERNAL_IOMGR_IOMGR_INTERNAL_H_ - -#include "src/core/iomgr/iomgr.h" -#include "src/core/iomgr/iomgr_internal.h" +/* Posix grpc event manager support code. */ +#include #include +#include -int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success); -void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg, - int success); - -void grpc_iomgr_ref(); -void grpc_iomgr_unref(); - -void grpc_iomgr_platform_init(); -void grpc_iomgr_platform_shutdown(); +static int error_code = 0; +static gpr_once threads_once = GPR_ONCE_INIT; +static void evthread_threads_initialize(void) { + error_code = evthread_use_pthreads(); + if (error_code) { + gpr_log(GPR_ERROR, "Failed to initialize libevent thread support!"); + } +} -#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_INTERNAL_H_ */ +/* Notify LibEvent that Posix pthread is used. */ +int evthread_use_threads() { + gpr_once_init(&threads_once, &evthread_threads_initialize); + /* For Pthreads or Windows threads, Libevent provides simple APIs to set + mutexes and conditional variables to support cross thread operations. + For other platforms, LibEvent provide callback APIs to hook mutexes and + conditional variables. */ + return error_code; +} diff --git a/src/core/iomgr/iomgr_posix.c b/src/core/iomgr/pollset.c similarity index 89% rename from src/core/iomgr/iomgr_posix.c rename to src/core/iomgr/pollset.c index ff9195ec1dc..62a0019eb33 100644 --- a/src/core/iomgr/iomgr_posix.c +++ b/src/core/iomgr/pollset.c @@ -31,8 +31,7 @@ * */ -#include "src/core/iomgr/iomgr_posix.h" +#include "src/core/iomgr/pollset.h" -void grpc_iomgr_platform_init() { grpc_pollset_global_init(); } - -void grpc_iomgr_platform_shutdown() { grpc_pollset_global_shutdown(); } +void grpc_pollset_init(grpc_pollset *pollset) { pollset->unused = 0; } +void grpc_pollset_destroy(grpc_pollset *pollset) {} diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h index 7374a4ec131..ba1a9d54296 100644 --- a/src/core/iomgr/pollset.h +++ b/src/core/iomgr/pollset.h @@ -34,31 +34,18 @@ #ifndef __GRPC_INTERNAL_IOMGR_POLLSET_H_ #define __GRPC_INTERNAL_IOMGR_POLLSET_H_ -#include - /* A grpc_pollset is a set of file descriptors that a higher level item is interested in. For example: - a server will typically keep a pollset containing all connected channels, so that it can find new calls to service - a completion queue might keep a pollset with an entry for each transport that is servicing a call that it's tracking */ - -#ifdef GPR_POSIX_SOCKET -#include "src/core/iomgr/pollset_posix.h" -#endif +/* Eventually different implementations of iomgr will provide their own + grpc_pollset structs. As this is just a dummy wrapper to get the API in, + we just define a simple type here. */ +typedef struct { char unused; } grpc_pollset; void grpc_pollset_init(grpc_pollset *pollset); 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. */ -int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline); - -/* Break a pollset out of polling work - Requires GRPC_POLLSET_MU(pollset) locked. */ -void grpc_pollset_kick(grpc_pollset *pollset); - #endif /* __GRPC_INTERNAL_IOMGR_POLLSET_H_ */ diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c deleted file mode 100644 index e482da94f7c..00000000000 --- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -#ifdef GPR_POSIX_MULTIPOLL_WITH_POLL - -#include "src/core/iomgr/pollset_posix.h" - -#include -#include -#include -#include - -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/iomgr_internal.h" -#include -#include -#include - -typedef struct { - /* all polled fds */ - size_t fd_count; - size_t fd_capacity; - grpc_fd **fds; - /* fds being polled by the current poller: parallel arrays of pollfd and the - * grpc_fd* that the pollfd was constructed from */ - size_t pfd_count; - size_t pfd_capacity; - grpc_fd **selfds; - struct pollfd *pfds; - /* fds that have been removed from the pollset explicitly */ - size_t del_count; - size_t del_capacity; - grpc_fd **dels; -} pollset_hdr; - -static void multipoll_with_poll_pollset_add_fd(grpc_pollset *pollset, - grpc_fd *fd) { - size_t i; - pollset_hdr *h = pollset->data.ptr; - /* TODO(ctiller): this is O(num_fds^2); maybe switch to a hash set here */ - for (i = 0; i < h->fd_count; i++) { - if (h->fds[i] == fd) return; - } - if (h->fd_count == h->fd_capacity) { - h->fd_capacity = GPR_MAX(h->fd_capacity + 8, h->fd_count * 3 / 2); - h->fds = gpr_realloc(h->fds, sizeof(grpc_fd *) * h->fd_capacity); - } - h->fds[h->fd_count++] = fd; - grpc_fd_ref(fd); -} - -static void multipoll_with_poll_pollset_del_fd(grpc_pollset *pollset, - grpc_fd *fd) { - /* will get removed next poll cycle */ - pollset_hdr *h = pollset->data.ptr; - if (h->del_count == h->del_capacity) { - h->del_capacity = GPR_MAX(h->del_capacity + 8, h->del_count * 3 / 2); - h->dels = gpr_realloc(h->dels, sizeof(grpc_fd *) * h->del_capacity); - } - h->dels[h->del_count++] = fd; - grpc_fd_ref(fd); -} - -static void end_polling(grpc_pollset *pollset) { - size_t i; - pollset_hdr *h; - h = pollset->data.ptr; - for (i = 1; i < h->pfd_count; i++) { - grpc_fd_end_poll(h->selfds[i], pollset); - } -} - -static int multipoll_with_poll_pollset_maybe_work( - grpc_pollset *pollset, gpr_timespec deadline, gpr_timespec now, - int allow_synchronous_callback) { - int timeout; - int r; - size_t i, np, nf, nd; - pollset_hdr *h; - - if (pollset->counter) { - return 0; - } - h = pollset->data.ptr; - if (gpr_time_cmp(deadline, gpr_inf_future) == 0) { - timeout = -1; - } else { - timeout = gpr_time_to_millis(gpr_time_sub(deadline, now)); - if (timeout <= 0) { - return 1; - } - } - if (h->pfd_capacity < h->fd_count + 1) { - h->pfd_capacity = GPR_MAX(h->pfd_capacity * 3 / 2, h->fd_count + 1); - gpr_free(h->pfds); - gpr_free(h->selfds); - h->pfds = gpr_malloc(sizeof(struct pollfd) * h->pfd_capacity); - h->selfds = gpr_malloc(sizeof(grpc_fd *) * h->pfd_capacity); - } - nf = 0; - np = 1; - h->pfds[0].fd = grpc_kick_read_fd(pollset); - h->pfds[0].events = POLLIN; - h->pfds[0].revents = POLLOUT; - for (i = 0; i < h->fd_count; i++) { - int remove = grpc_fd_is_orphaned(h->fds[i]); - for (nd = 0; nd < h->del_count; nd++) { - if (h->fds[i] == h->dels[nd]) remove = 1; - } - if (remove) { - grpc_fd_unref(h->fds[i]); - } else { - h->fds[nf++] = h->fds[i]; - h->pfds[np].events = - grpc_fd_begin_poll(h->fds[i], pollset, POLLIN, POLLOUT); - h->selfds[np] = h->fds[i]; - h->pfds[np].fd = h->fds[i]->fd; - h->pfds[np].revents = 0; - np++; - } - } - h->pfd_count = np; - h->fd_count = nf; - for (nd = 0; nd < h->del_count; nd++) { - grpc_fd_unref(h->dels[nd]); - } - h->del_count = 0; - if (h->pfd_count == 0) { - end_polling(pollset); - return 0; - } - pollset->counter = 1; - gpr_mu_unlock(&pollset->mu); - - r = poll(h->pfds, h->pfd_count, timeout); - if (r < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - } else if (r == 0) { - /* do nothing */ - } else { - if (h->pfds[0].revents & POLLIN) { - grpc_kick_drain(pollset); - } - for (i = 1; i < np; i++) { - if (h->pfds[i].revents & POLLIN) { - grpc_fd_become_readable(h->selfds[i], allow_synchronous_callback); - } - if (h->pfds[i].revents & POLLOUT) { - grpc_fd_become_writable(h->selfds[i], allow_synchronous_callback); - } - } - } - end_polling(pollset); - - gpr_mu_lock(&pollset->mu); - pollset->counter = 0; - gpr_cv_broadcast(&pollset->cv); - return 1; -} - -static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) { - size_t i; - pollset_hdr *h = pollset->data.ptr; - GPR_ASSERT(pollset->counter == 0); - for (i = 0; i < h->fd_count; i++) { - grpc_fd_unref(h->fds[i]); - } - for (i = 0; i < h->del_count; i++) { - grpc_fd_unref(h->dels[i]); - } - gpr_free(h->pfds); - gpr_free(h->selfds); - gpr_free(h->fds); - gpr_free(h->dels); - gpr_free(h); -} - -static const grpc_pollset_vtable multipoll_with_poll_pollset = { - multipoll_with_poll_pollset_add_fd, multipoll_with_poll_pollset_del_fd, - multipoll_with_poll_pollset_maybe_work, - multipoll_with_poll_pollset_destroy}; - -void grpc_platform_become_multipoller(grpc_pollset *pollset, grpc_fd **fds, - size_t nfds) { - size_t i; - pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr)); - pollset->vtable = &multipoll_with_poll_pollset; - pollset->data.ptr = h; - h->fd_count = nfds; - h->fd_capacity = nfds; - h->fds = gpr_malloc(nfds * sizeof(grpc_fd *)); - h->pfd_count = 0; - h->pfd_capacity = 0; - h->pfds = NULL; - h->selfds = NULL; - h->del_count = 0; - h->del_capacity = 0; - h->dels = NULL; - for (i = 0; i < nfds; i++) { - h->fds[i] = fds[i]; - grpc_fd_ref(fds[i]); - } -} - -#endif diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c deleted file mode 100644 index ff00e064291..00000000000 --- a/src/core/iomgr/pollset_posix.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/pollset_posix.h" - -#include -#include -#include -#include -#include - -#include "src/core/iomgr/alarm_internal.h" -#include "src/core/iomgr/fd_posix.h" -#include "src/core/iomgr/iomgr_internal.h" -#include "src/core/iomgr/socket_utils_posix.h" -#include -#include -#include -#include - -/* kick pipes: we keep a sharded set of pipes to allow breaking from poll. - Ideally this would be 1:1 with pollsets, but we'd like to avoid associating - full kernel objects with each pollset to keep them lightweight, so instead - keep a sharded set and allow associating a pollset with one of the shards. - - TODO(ctiller): move this out from this file, and allow an eventfd - implementation on linux */ - -#define LOG2_KICK_SHARDS 6 -#define KICK_SHARDS (1 << LOG2_KICK_SHARDS) - -static int g_kick_pipes[KICK_SHARDS][2]; -static grpc_pollset g_backup_pollset; -static int g_shutdown_backup_poller; -static gpr_event g_backup_poller_done; - -static void backup_poller(void *p) { - gpr_timespec delta = gpr_time_from_millis(100); - gpr_timespec last_poll = gpr_now(); - - gpr_mu_lock(&g_backup_pollset.mu); - while (g_shutdown_backup_poller == 0) { - gpr_timespec next_poll = gpr_time_add(last_poll, delta); - grpc_pollset_work(&g_backup_pollset, next_poll); - gpr_mu_unlock(&g_backup_pollset.mu); - gpr_sleep_until(next_poll); - gpr_mu_lock(&g_backup_pollset.mu); - last_poll = next_poll; - } - gpr_mu_unlock(&g_backup_pollset.mu); - - gpr_event_set(&g_backup_poller_done, (void *)1); -} - -static size_t kick_shard(const grpc_pollset *info) { - size_t x = (size_t)info; - return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (KICK_SHARDS - 1); -} - -int grpc_kick_read_fd(grpc_pollset *p) { - return g_kick_pipes[kick_shard(p)][0]; -} - -static int grpc_kick_write_fd(grpc_pollset *p) { - return g_kick_pipes[kick_shard(p)][1]; -} - -void grpc_pollset_force_kick(grpc_pollset *p) { - char c = 0; - while (write(grpc_kick_write_fd(p), &c, 1) != 1 && errno == EINTR) - ; -} - -void grpc_pollset_kick(grpc_pollset *p) { - if (!p->counter) return; - grpc_pollset_force_kick(p); -} - -void grpc_kick_drain(grpc_pollset *p) { - int fd = grpc_kick_read_fd(p); - char buf[128]; - int r; - - for (;;) { - r = read(fd, buf, sizeof(buf)); - if (r > 0) continue; - if (r == 0) return; - switch (errno) { - case EAGAIN: - return; - case EINTR: - continue; - default: - gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno)); - return; - } - } -} - -/* global state management */ - -grpc_pollset *grpc_backup_pollset() { return &g_backup_pollset; } - -void grpc_pollset_global_init() { - int i; - gpr_thd_id id; - - /* initialize the kick shards */ - for (i = 0; i < KICK_SHARDS; i++) { - GPR_ASSERT(0 == pipe(g_kick_pipes[i])); - GPR_ASSERT(grpc_set_socket_nonblocking(g_kick_pipes[i][0], 1)); - GPR_ASSERT(grpc_set_socket_nonblocking(g_kick_pipes[i][1], 1)); - } - - /* initialize the backup pollset */ - grpc_pollset_init(&g_backup_pollset); - - /* start the backup poller thread */ - g_shutdown_backup_poller = 0; - gpr_event_init(&g_backup_poller_done); - gpr_thd_new(&id, backup_poller, NULL, NULL); -} - -void grpc_pollset_global_shutdown() { - int i; - - /* terminate the backup poller thread */ - gpr_mu_lock(&g_backup_pollset.mu); - g_shutdown_backup_poller = 1; - gpr_mu_unlock(&g_backup_pollset.mu); - gpr_event_wait(&g_backup_poller_done, gpr_inf_future); - - /* destroy the backup pollset */ - grpc_pollset_destroy(&g_backup_pollset); - - /* destroy the kick shards */ - for (i = 0; i < KICK_SHARDS; i++) { - close(g_kick_pipes[i][0]); - close(g_kick_pipes[i][1]); - } -} - -/* main interface */ - -static void become_empty_pollset(grpc_pollset *pollset); -static void become_unary_pollset(grpc_pollset *pollset, grpc_fd *fd); - -void grpc_pollset_init(grpc_pollset *pollset) { - gpr_mu_init(&pollset->mu); - gpr_cv_init(&pollset->cv); - become_empty_pollset(pollset); -} - -void grpc_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { - gpr_mu_lock(&pollset->mu); - pollset->vtable->add_fd(pollset, fd); - gpr_cv_broadcast(&pollset->cv); - gpr_mu_unlock(&pollset->mu); -} - -void grpc_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) { - gpr_mu_lock(&pollset->mu); - pollset->vtable->del_fd(pollset, fd); - gpr_cv_broadcast(&pollset->cv); - gpr_mu_unlock(&pollset->mu); -} - -int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { - /* pollset->mu already held */ - gpr_timespec now; - now = gpr_now(); - if (gpr_time_cmp(now, deadline) > 0) { - return 0; - } - if (grpc_maybe_call_delayed_callbacks(&pollset->mu, 1)) { - return 1; - } - if (grpc_alarm_check(&pollset->mu, now, &deadline)) { - return 1; - } - return pollset->vtable->maybe_work(pollset, deadline, now, 1); -} - -void grpc_pollset_destroy(grpc_pollset *pollset) { - pollset->vtable->destroy(pollset); - gpr_mu_destroy(&pollset->mu); - gpr_cv_destroy(&pollset->cv); -} - -/* - * empty_pollset - a vtable that provides polling for NO file descriptors - */ - -static void empty_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { - become_unary_pollset(pollset, fd); -} - -static void empty_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) {} - -static int empty_pollset_maybe_work(grpc_pollset *pollset, - gpr_timespec deadline, gpr_timespec now, - int allow_synchronous_callback) { - return 0; -} - -static void empty_pollset_destroy(grpc_pollset *pollset) {} - -static const grpc_pollset_vtable empty_pollset = { - empty_pollset_add_fd, empty_pollset_del_fd, empty_pollset_maybe_work, - empty_pollset_destroy}; - -static void become_empty_pollset(grpc_pollset *pollset) { - pollset->vtable = &empty_pollset; -} - -/* - * unary_poll_pollset - a vtable that provides polling for one file descriptor - * via poll() - */ - -static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { - grpc_fd *fds[2]; - if (fd == pollset->data.ptr) return; - fds[0] = pollset->data.ptr; - fds[1] = fd; - grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); - grpc_fd_unref(fds[0]); -} - -static void unary_poll_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) { - if (fd == pollset->data.ptr) { - grpc_fd_unref(pollset->data.ptr); - become_empty_pollset(pollset); - } -} - -static int unary_poll_pollset_maybe_work(grpc_pollset *pollset, - gpr_timespec deadline, - gpr_timespec now, - int allow_synchronous_callback) { - struct pollfd pfd[2]; - grpc_fd *fd; - int timeout; - int r; - - if (pollset->counter) { - return 0; - } - fd = pollset->data.ptr; - if (grpc_fd_is_orphaned(fd)) { - grpc_fd_unref(fd); - become_empty_pollset(pollset); - return 0; - } - if (gpr_time_cmp(deadline, gpr_inf_future) == 0) { - timeout = -1; - } else { - timeout = gpr_time_to_millis(gpr_time_sub(deadline, now)); - if (timeout <= 0) { - return 1; - } - } - pfd[0].fd = grpc_kick_read_fd(pollset); - pfd[0].events = POLLIN; - pfd[0].revents = 0; - pfd[1].fd = fd->fd; - pfd[1].events = grpc_fd_begin_poll(fd, pollset, POLLIN, POLLOUT); - pfd[1].revents = 0; - pollset->counter = 1; - gpr_mu_unlock(&pollset->mu); - - r = poll(pfd, GPR_ARRAY_SIZE(pfd), timeout); - if (r < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - } else if (r == 0) { - /* do nothing */ - } else { - if (pfd[0].revents & POLLIN) { - grpc_kick_drain(pollset); - } - if (pfd[1].revents & POLLIN) { - grpc_fd_become_readable(fd, allow_synchronous_callback); - } - if (pfd[1].revents & POLLOUT) { - grpc_fd_become_writable(fd, allow_synchronous_callback); - } - } - - gpr_mu_lock(&pollset->mu); - grpc_fd_end_poll(fd, pollset); - pollset->counter = 0; - gpr_cv_broadcast(&pollset->cv); - return 1; -} - -static void unary_poll_pollset_destroy(grpc_pollset *pollset) { - GPR_ASSERT(pollset->counter == 0); - grpc_fd_unref(pollset->data.ptr); -} - -static const grpc_pollset_vtable unary_poll_pollset = { - unary_poll_pollset_add_fd, unary_poll_pollset_del_fd, - unary_poll_pollset_maybe_work, unary_poll_pollset_destroy}; - -static void become_unary_pollset(grpc_pollset *pollset, grpc_fd *fd) { - pollset->vtable = &unary_poll_pollset; - pollset->counter = 0; - pollset->data.ptr = fd; - grpc_fd_ref(fd); -} diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h deleted file mode 100644 index f051079f5b5..00000000000 --- a/src/core/iomgr/pollset_posix.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_POSIX_H_ -#define __GRPC_INTERNAL_IOMGR_POLLSET_POSIX_H_ - -#include - -typedef struct grpc_pollset_vtable grpc_pollset_vtable; - -/* forward declare only in this file to avoid leaking impl details via - pollset.h; real users of grpc_fd should always include 'fd_posix.h' and not - use the struct tag */ -struct grpc_fd; - -typedef struct grpc_pollset { - /* pollsets under posix can mutate representation as fds are added and - removed. - For example, we may choose a poll() based implementation on linux for - few fds, and an epoll() based implementation for many fds */ - const grpc_pollset_vtable *vtable; - gpr_mu mu; - gpr_cv cv; - int counter; - union { - int fd; - void *ptr; - } data; -} grpc_pollset; - -struct grpc_pollset_vtable { - void (*add_fd)(grpc_pollset *pollset, struct grpc_fd *fd); - void (*del_fd)(grpc_pollset *pollset, struct grpc_fd *fd); - int (*maybe_work)(grpc_pollset *pollset, gpr_timespec deadline, - gpr_timespec now, int allow_synchronous_callback); - void (*destroy)(grpc_pollset *pollset); -}; - -#define GRPC_POLLSET_MU(pollset) (&(pollset)->mu) -#define GRPC_POLLSET_CV(pollset) (&(pollset)->cv) - -/* Add an fd to a pollset */ -void grpc_pollset_add_fd(grpc_pollset *pollset, struct grpc_fd *fd); -/* Force remove an fd from a pollset (normally they are removed on the next - poll after an fd is orphaned) */ -void grpc_pollset_del_fd(grpc_pollset *pollset, struct grpc_fd *fd); - -/* Force any current pollers to break polling */ -void grpc_pollset_force_kick(grpc_pollset *pollset); -/* Returns the fd to listen on for kicks */ -int grpc_kick_read_fd(grpc_pollset *p); -/* Call after polling has been kicked to leave the kicked state */ -void grpc_kick_drain(grpc_pollset *p); - -/* All fds get added to a backup pollset to ensure that progress is made - regardless of applications listening to events. Relying on this is slow - however (the backup pollset only listens every 100ms or so) - so it's not - to be relied on. */ -grpc_pollset *grpc_backup_pollset(); - -/* turn a pollset into a multipoller: platform specific */ -void grpc_platform_become_multipoller(grpc_pollset *pollset, - struct grpc_fd **fds, size_t fd_count); - -#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_POSIX_H_ */ diff --git a/src/core/iomgr/resolve_address_posix.c b/src/core/iomgr/resolve_address_posix.c index c9c2c5378a5..a0a04297eb1 100644 --- a/src/core/iomgr/resolve_address_posix.c +++ b/src/core/iomgr/resolve_address_posix.c @@ -41,7 +41,7 @@ #include #include -#include "src/core/iomgr/iomgr_internal.h" +#include "src/core/iomgr/iomgr_libevent.h" #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include @@ -201,7 +201,7 @@ static void do_request(void *rp) { gpr_free(r->default_port); gpr_free(r); cb(arg, resolved); - grpc_iomgr_unref(); + grpc_iomgr_ref_address_resolution(-1); } void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { @@ -213,7 +213,7 @@ void grpc_resolve_address(const char *name, const char *default_port, grpc_resolve_cb cb, void *arg) { request *r = gpr_malloc(sizeof(request)); gpr_thd_id id; - grpc_iomgr_ref(); + grpc_iomgr_ref_address_resolution(1); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->cb = cb; diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c index d675c2dcece..88b599b582e 100644 --- a/src/core/iomgr/tcp_client_posix.c +++ b/src/core/iomgr/tcp_client_posix.c @@ -38,9 +38,7 @@ #include #include -#include "src/core/iomgr/alarm.h" -#include "src/core/iomgr/iomgr_posix.h" -#include "src/core/iomgr/pollset_posix.h" +#include "src/core/iomgr/iomgr_libevent.h" #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include "src/core/iomgr/tcp_posix.h" @@ -51,11 +49,8 @@ typedef struct { void (*cb)(void *arg, grpc_endpoint *tcp); void *cb_arg; - gpr_mu mu; grpc_fd *fd; gpr_timespec deadline; - grpc_alarm alarm; - int refs; } async_connect; static int prepare_socket(int fd) { @@ -79,42 +74,21 @@ error: return 0; } -static void on_alarm(void *acp, int success) { - int done; - async_connect *ac = acp; - gpr_mu_lock(&ac->mu); - if (ac->fd != NULL && success) { - grpc_fd_shutdown(ac->fd); - } - done = (--ac->refs == 0); - gpr_mu_unlock(&ac->mu); - if (done) { - gpr_mu_destroy(&ac->mu); - gpr_free(ac); - } -} - -static void on_writable(void *acp, int success) { +static void on_writable(void *acp, grpc_iomgr_cb_status status) { async_connect *ac = acp; int so_error = 0; socklen_t so_error_size; int err; - int fd = ac->fd->fd; - int done; - grpc_endpoint *ep = NULL; - void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb; - void *cb_arg = ac->cb_arg; - - grpc_alarm_cancel(&ac->alarm); + int fd = grpc_fd_get(ac->fd); - if (success) { + if (status == GRPC_CALLBACK_SUCCESS) { do { so_error_size = sizeof(so_error); err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size); } while (err < 0 && errno == EINTR); if (err < 0) { gpr_log(GPR_ERROR, "getsockopt(ERROR): %s", strerror(errno)); - goto finish; + goto error; } else if (so_error != 0) { if (so_error == ENOBUFS) { /* We will get one of these errors if we have run out of @@ -132,7 +106,7 @@ static void on_writable(void *acp, int success) { opened too many network connections. The "easy" fix: don't do that! */ gpr_log(GPR_ERROR, "kernel out of buffers"); - grpc_fd_notify_on_write(ac->fd, on_writable, ac); + grpc_fd_notify_on_write(ac->fd, on_writable, ac, ac->deadline); return; } else { switch (so_error) { @@ -143,31 +117,27 @@ static void on_writable(void *acp, int success) { gpr_log(GPR_ERROR, "socket error: %d", so_error); break; } - goto finish; + goto error; } } else { - ep = grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE); - goto finish; + goto great_success; } } else { - gpr_log(GPR_ERROR, "on_writable failed during connect"); - goto finish; + gpr_log(GPR_ERROR, "on_writable failed during connect: status=%d", status); + goto error; } abort(); -finish: - gpr_mu_lock(&ac->mu); - if (!ep) { - grpc_fd_orphan(ac->fd, NULL, NULL); - } - done = (--ac->refs == 0); - gpr_mu_unlock(&ac->mu); - if (done) { - gpr_mu_destroy(&ac->mu); - gpr_free(ac); - } - cb(cb_arg, ep); +error: + ac->cb(ac->cb_arg, NULL); + grpc_fd_destroy(ac->fd, NULL, NULL); + gpr_free(ac); + return; + +great_success: + ac->cb(ac->cb_arg, grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); + gpr_free(ac); } void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), @@ -206,7 +176,6 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), } while (err < 0 && errno == EINTR); if (err >= 0) { - gpr_log(GPR_DEBUG, "instant connect"); cb(arg, grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); return; @@ -222,10 +191,7 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), ac = gpr_malloc(sizeof(async_connect)); ac->cb = cb; ac->cb_arg = arg; + ac->deadline = deadline; ac->fd = grpc_fd_create(fd); - gpr_mu_init(&ac->mu); - ac->refs = 2; - - grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); - grpc_fd_notify_on_write(ac->fd, on_writable, ac); + grpc_fd_notify_on_write(ac->fd, on_writable, ac, deadline); } diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 657f34aaf99..bc3ce69e471 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -255,14 +255,18 @@ typedef struct { grpc_endpoint_read_cb read_cb; void *read_user_data; + gpr_timespec read_deadline; grpc_endpoint_write_cb write_cb; void *write_user_data; + gpr_timespec write_deadline; grpc_tcp_slice_state write_state; } grpc_tcp; -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success); +static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, + grpc_iomgr_cb_status status); +static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, + grpc_iomgr_cb_status status); static void grpc_tcp_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; @@ -272,7 +276,7 @@ static void grpc_tcp_shutdown(grpc_endpoint *ep) { static void grpc_tcp_unref(grpc_tcp *tcp) { int refcount_zero = gpr_unref(&tcp->refcount); if (refcount_zero) { - grpc_fd_orphan(tcp->em_fd, NULL, NULL); + grpc_fd_destroy(tcp->em_fd, NULL, NULL); gpr_free(tcp); } } @@ -304,7 +308,8 @@ static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices, #define INLINE_SLICE_BUFFER_SIZE 8 #define MAX_READ_IOVEC 4 -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { +static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, + grpc_iomgr_cb_status status) { grpc_tcp *tcp = (grpc_tcp *)arg; int iov_size = 1; gpr_slice static_read_slices[INLINE_SLICE_BUFFER_SIZE]; @@ -319,12 +324,18 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { slice_state_init(&read_state, static_read_slices, INLINE_SLICE_BUFFER_SIZE, 0); - if (!success) { + if (status == GRPC_CALLBACK_CANCELLED) { call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); grpc_tcp_unref(tcp); return; } + if (status == GRPC_CALLBACK_TIMED_OUT) { + call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_TIMED_OUT); + grpc_tcp_unref(tcp); + return; + } + /* TODO(klempner): Limit the amount we read at once. */ for (;;) { allocated_bytes = slice_state_append_blocks_into_iovec( @@ -366,7 +377,8 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { } else { /* Spurious read event, consume it here */ slice_state_destroy(&read_state); - grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp); + grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp, + tcp->read_deadline); } } else { /* TODO(klempner): Log interesting errors */ @@ -395,13 +407,14 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { } static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data) { + void *user_data, gpr_timespec deadline) { grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(tcp->read_cb == NULL); tcp->read_cb = cb; tcp->read_user_data = user_data; + tcp->read_deadline = deadline; gpr_ref(&tcp->refcount); - grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp); + grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp, deadline); } #define MAX_WRITE_IOVEC 16 @@ -447,24 +460,34 @@ static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { }; } -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { +static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, + grpc_iomgr_cb_status status) { grpc_tcp *tcp = (grpc_tcp *)arg; grpc_endpoint_write_status write_status; grpc_endpoint_cb_status cb_status; grpc_endpoint_write_cb cb; - if (!success) { + cb_status = GRPC_ENDPOINT_CB_OK; + + if (status == GRPC_CALLBACK_CANCELLED) { + cb_status = GRPC_ENDPOINT_CB_SHUTDOWN; + } else if (status == GRPC_CALLBACK_TIMED_OUT) { + cb_status = GRPC_ENDPOINT_CB_TIMED_OUT; + } + + if (cb_status != GRPC_ENDPOINT_CB_OK) { slice_state_destroy(&tcp->write_state); cb = tcp->write_cb; tcp->write_cb = NULL; - cb(tcp->write_user_data, GRPC_ENDPOINT_CB_SHUTDOWN); + cb(tcp->write_user_data, cb_status); grpc_tcp_unref(tcp); return; } write_status = grpc_tcp_flush(tcp); if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { - grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp); + grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp, + tcp->write_deadline); } else { slice_state_destroy(&tcp->write_state); if (write_status == GRPC_ENDPOINT_WRITE_DONE) { @@ -479,11 +502,9 @@ static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { } } -static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { +static grpc_endpoint_write_status grpc_tcp_write( + grpc_endpoint *ep, gpr_slice *slices, size_t nslices, + grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_endpoint_write_status status; @@ -509,15 +530,17 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, gpr_ref(&tcp->refcount); tcp->write_cb = cb; tcp->write_user_data = user_data; - grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp); + tcp->write_deadline = deadline; + grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp, + tcp->write_deadline); } return status; } static void grpc_tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { - grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_pollset_add_fd(pollset, tcp->em_fd); + /* tickle the pollset so we crash if things aren't wired correctly */ + pollset->unused++; } static const grpc_endpoint_vtable vtable = { @@ -527,12 +550,14 @@ static const grpc_endpoint_vtable vtable = { grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); tcp->base.vtable = &vtable; - tcp->fd = em_fd->fd; + tcp->fd = grpc_fd_get(em_fd); tcp->read_cb = NULL; tcp->write_cb = NULL; tcp->read_user_data = NULL; tcp->write_user_data = NULL; tcp->slice_size = slice_size; + tcp->read_deadline = gpr_inf_future; + tcp->write_deadline = gpr_inf_future; slice_state_init(&tcp->write_state, NULL, 0, 0); /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); diff --git a/src/core/iomgr/tcp_posix.h b/src/core/iomgr/tcp_posix.h index c3eef1b4b73..830394d5344 100644 --- a/src/core/iomgr/tcp_posix.h +++ b/src/core/iomgr/tcp_posix.h @@ -45,7 +45,7 @@ */ #include "src/core/iomgr/endpoint.h" -#include "src/core/iomgr/fd_posix.h" +#include "src/core/iomgr/iomgr_libevent.h" #define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192 diff --git a/src/core/iomgr/tcp_server.h b/src/core/iomgr/tcp_server.h index 1968246b751..46fba13f901 100644 --- a/src/core/iomgr/tcp_server.h +++ b/src/core/iomgr/tcp_server.h @@ -49,8 +49,8 @@ typedef void (*grpc_tcp_server_cb)(void *arg, grpc_endpoint *ep); grpc_tcp_server *grpc_tcp_server_create(); /* Start listening to bound ports */ -void grpc_tcp_server_start(grpc_tcp_server *server, grpc_pollset *pollset, - grpc_tcp_server_cb cb, void *cb_arg); +void grpc_tcp_server_start(grpc_tcp_server *server, grpc_tcp_server_cb cb, + void *cb_arg); /* Add a port to the server, returning true on success, or false otherwise. diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c index 5ed517748a3..2abaf15ce4d 100644 --- a/src/core/iomgr/tcp_server_posix.c +++ b/src/core/iomgr/tcp_server_posix.c @@ -45,7 +45,7 @@ #include #include -#include "src/core/iomgr/pollset_posix.h" +#include "src/core/iomgr/iomgr_libevent.h" #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include "src/core/iomgr/tcp_posix.h" @@ -97,8 +97,13 @@ grpc_tcp_server *grpc_tcp_server_create() { return s; } +static void done_destroy(void *p, grpc_iomgr_cb_status status) { + gpr_event_set(p, (void *)1); +} + void grpc_tcp_server_destroy(grpc_tcp_server *s) { size_t i; + gpr_event fd_done; gpr_mu_lock(&s->mu); /* shutdown all fd's */ for (i = 0; i < s->nports; i++) { @@ -113,7 +118,9 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s) { /* delete ALL the things */ for (i = 0; i < s->nports; i++) { server_port *sp = &s->ports[i]; - grpc_fd_orphan(sp->emfd, NULL, NULL); + gpr_event_init(&fd_done); + grpc_fd_destroy(sp->emfd, done_destroy, &fd_done); + gpr_event_wait(&fd_done, gpr_inf_future); } gpr_free(s->ports); gpr_free(s); @@ -189,10 +196,10 @@ error: } /* event manager callback when reads are ready */ -static void on_read(void *arg, int success) { +static void on_read(void *arg, grpc_iomgr_cb_status status) { server_port *sp = arg; - if (!success) { + if (status != GRPC_CALLBACK_SUCCESS) { goto error; } @@ -208,7 +215,7 @@ static void on_read(void *arg, int success) { case EINTR: continue; case EAGAIN: - grpc_fd_notify_on_read(sp->emfd, on_read, sp); + grpc_fd_notify_on_read(sp->emfd, on_read, sp, gpr_inf_future); return; default: gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); @@ -247,10 +254,15 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd, s->ports = gpr_realloc(s->ports, sizeof(server_port *) * s->port_capacity); } sp = &s->ports[s->nports++]; - sp->server = s; - sp->fd = fd; sp->emfd = grpc_fd_create(fd); - GPR_ASSERT(sp->emfd); + sp->fd = fd; + sp->server = s; + /* initialize the em desc */ + if (sp->emfd == NULL) { + s->nports--; + gpr_mu_unlock(&s->mu); + return 0; + } gpr_mu_unlock(&s->mu); return 1; @@ -307,8 +319,8 @@ int grpc_tcp_server_get_fd(grpc_tcp_server *s, int index) { return (0 <= index && index < s->nports) ? s->ports[index].fd : -1; } -void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset *pollset, - grpc_tcp_server_cb cb, void *cb_arg) { +void grpc_tcp_server_start(grpc_tcp_server *s, grpc_tcp_server_cb cb, + void *cb_arg) { size_t i; GPR_ASSERT(cb); gpr_mu_lock(&s->mu); @@ -317,10 +329,8 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset *pollset, s->cb = cb; s->cb_arg = cb_arg; for (i = 0; i < s->nports; i++) { - if (pollset) { - grpc_pollset_add_fd(pollset, s->ports[i].emfd); - } - grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i]); + grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i], + gpr_inf_future); s->active_ports++; } gpr_mu_unlock(&s->mu); diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index c99ac8021d9..442d2fa6249 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -555,11 +555,12 @@ static int fake_oauth2_has_request_metadata_only( return 1; } -void on_simulated_token_fetch_done(void *user_data, int success) { +void on_simulated_token_fetch_done(void *user_data, + grpc_iomgr_cb_status status) { grpc_credentials_metadata_request *r = (grpc_credentials_metadata_request *)user_data; grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)r->creds; - GPR_ASSERT(success); + GPR_ASSERT(status == GRPC_CALLBACK_SUCCESS); r->cb(r->user_data, &c->access_token_md, 1, GRPC_CREDENTIALS_OK); grpc_credentials_metadata_request_destroy(r); } diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c index 7f0fdf73c97..cab09ca49d3 100644 --- a/src/core/security/secure_endpoint.c +++ b/src/core/security/secure_endpoint.c @@ -184,7 +184,8 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, } static void endpoint_notify_on_read(grpc_endpoint *secure_ep, - grpc_endpoint_read_cb cb, void *user_data) { + grpc_endpoint_read_cb cb, void *user_data, + gpr_timespec deadline) { secure_endpoint *ep = (secure_endpoint *)secure_ep; ep->read_cb = cb; ep->read_user_data = user_data; @@ -199,7 +200,7 @@ static void endpoint_notify_on_read(grpc_endpoint *secure_ep, return; } - grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep); + grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep, deadline); } static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, @@ -216,11 +217,9 @@ static void on_write(void *data, grpc_endpoint_cb_status error) { secure_endpoint_unref(ep); } -static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { +static grpc_endpoint_write_status endpoint_write( + grpc_endpoint *secure_ep, gpr_slice *slices, size_t nslices, + grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline) { int i = 0; int output_buffer_count = 0; tsi_result result = TSI_OK; @@ -309,7 +308,7 @@ static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, /* Need to keep the endpoint alive across a transport */ secure_endpoint_ref(ep); status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices, - output_buffer_count, on_write, ep); + output_buffer_count, on_write, ep, deadline); if (status != GRPC_ENDPOINT_WRITE_PENDING) { secure_endpoint_unref(ep); } diff --git a/src/core/security/secure_transport_setup.c b/src/core/security/secure_transport_setup.c index 3df91ed8e7f..eb112519121 100644 --- a/src/core/security/secure_transport_setup.c +++ b/src/core/security/secure_transport_setup.c @@ -105,7 +105,6 @@ static void check_peer(grpc_secure_transport_setup *s) { grpc_security_status peer_status; tsi_peer peer; tsi_result result = tsi_handshaker_extract_peer(s->handshaker, &peer); - if (result != TSI_OK) { gpr_log(GPR_ERROR, "Peer extraction failed with error %s", tsi_result_to_string(result)); @@ -153,8 +152,9 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { gpr_slice_from_copied_buffer((const char *)s->handshake_buffer, offset); /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - write_status = grpc_endpoint_write(s->endpoint, &to_send, 1, - on_handshake_data_sent_to_peer, s); + write_status = + grpc_endpoint_write(s->endpoint, &to_send, 1, + on_handshake_data_sent_to_peer, s, gpr_inf_future); if (write_status == GRPC_ENDPOINT_WRITE_ERROR) { gpr_log(GPR_ERROR, "Could not send handshake data to peer."); secure_transport_setup_done(s, 0); @@ -200,7 +200,8 @@ static void on_handshake_data_received_from_peer( /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ grpc_endpoint_notify_on_read(s->endpoint, - on_handshake_data_received_from_peer, setup); + on_handshake_data_received_from_peer, setup, + gpr_inf_future); cleanup_slices(slices, nslices); return; } else { @@ -257,7 +258,8 @@ static void on_handshake_data_sent_to_peer(void *setup, /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ grpc_endpoint_notify_on_read(s->endpoint, - on_handshake_data_received_from_peer, setup); + on_handshake_data_received_from_peer, setup, + gpr_inf_future); } else { check_peer(s); } diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index 9d7c0e5e5a8..28b56dd4c9d 100644 --- a/src/core/security/server_secure_chttp2.c +++ b/src/core/security/server_secure_chttp2.c @@ -77,9 +77,9 @@ static void on_accept(void *server, grpc_endpoint *tcp) { /* Note: the following code is the same with server_chttp2.c */ /* Server callback: start listening on our ports */ -static void start(grpc_server *server, void *tcpp, grpc_pollset *pollset) { +static void start(grpc_server *server, void *tcpp) { grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(tcp, pollset, on_accept, server); + grpc_tcp_server_start(tcp, on_accept, server); } /* Server callback: destroy the tcp listener (so we don't generate further diff --git a/src/core/support/time.c b/src/core/support/time.c index 5330092f56b..712bdf441cf 100644 --- a/src/core/support/time.c +++ b/src/core/support/time.c @@ -249,18 +249,3 @@ gpr_timespec gpr_timespec_from_timeval(struct timeval t) { ts.tv_nsec = t.tv_usec * 1000; return ts; } - -gpr_int32 gpr_time_to_millis(gpr_timespec t) { - if (t.tv_sec >= 2147483) { - if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) { - return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS; - } - return 2147483647; - } else if (t.tv_sec <= -2147483) { - /* TODO(ctiller): correct handling here (it's so far in the past do we - care?) */ - return -2147483648; - } else { - return t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS; - } -} diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 9c5f5064eba..9ed617f665c 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -878,9 +878,9 @@ grpc_metadata_buffer *grpc_call_get_metadata_buffer(grpc_call *call) { return &call->incoming_metadata; } -static void call_alarm(void *arg, int success) { +static void call_alarm(void *arg, grpc_iomgr_cb_status status) { grpc_call *call = arg; - if (success) { + if (status == GRPC_CALLBACK_SUCCESS) { grpc_call_cancel(call); } grpc_call_internal_unref(call); diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index b59c36e03a7..4837f5b978e 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -36,7 +36,7 @@ #include #include -#include "src/core/iomgr/pollset.h" +#include "src/core/iomgr/iomgr_completion_queue_interface.h" #include "src/core/surface/call.h" #include "src/core/surface/event_string.h" #include "src/core/surface/surface_trace.h" @@ -61,7 +61,6 @@ typedef struct event { /* Completion queue structure */ struct grpc_completion_queue { - /* TODO(ctiller): see if this can be removed */ int allow_polling; /* When refs drops to zero, we are in shutdown mode, and will be destroyable @@ -101,7 +100,7 @@ void grpc_completion_queue_dont_poll_test_only(grpc_completion_queue *cc) { /* Create and append an event to the queue. Returns the event so that its data members can be filled in. - Requires GRPC_POLLSET_MU(&cc->pollset) locked. */ + Requires grpc_iomgr_mu locked. */ static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type, void *tag, grpc_call *call, grpc_event_finish_func on_finish, void *user_data) { @@ -127,8 +126,7 @@ static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type, ev->bucket_prev = cc->buckets[bucket]->bucket_prev; ev->bucket_next->bucket_prev = ev->bucket_prev->bucket_next = ev; } - gpr_cv_broadcast(GRPC_POLLSET_CV(&cc->pollset)); - grpc_pollset_kick(&cc->pollset); + gpr_cv_broadcast(&grpc_iomgr_cv); return ev; } @@ -151,7 +149,7 @@ static void end_op_locked(grpc_completion_queue *cc, if (gpr_unref(&cc->refs)) { GPR_ASSERT(!cc->shutdown); cc->shutdown = 1; - gpr_cv_broadcast(GRPC_POLLSET_CV(&cc->pollset)); + gpr_cv_broadcast(&grpc_iomgr_cv); } } @@ -159,11 +157,11 @@ void grpc_cq_end_read(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_event_finish_func on_finish, void *user_data, grpc_byte_buffer *read) { event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); ev = add_locked(cc, GRPC_READ, tag, call, on_finish, user_data); ev->base.data.read = read; end_op_locked(cc, GRPC_READ); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); } void grpc_cq_end_invoke_accepted(grpc_completion_queue *cc, void *tag, @@ -171,11 +169,11 @@ void grpc_cq_end_invoke_accepted(grpc_completion_queue *cc, void *tag, grpc_event_finish_func on_finish, void *user_data, grpc_op_error error) { event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); ev = add_locked(cc, GRPC_INVOKE_ACCEPTED, tag, call, on_finish, user_data); ev->base.data.invoke_accepted = error; end_op_locked(cc, GRPC_INVOKE_ACCEPTED); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); } void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, @@ -183,11 +181,11 @@ void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, grpc_event_finish_func on_finish, void *user_data, grpc_op_error error) { event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); ev = add_locked(cc, GRPC_WRITE_ACCEPTED, tag, call, on_finish, user_data); ev->base.data.write_accepted = error; end_op_locked(cc, GRPC_WRITE_ACCEPTED); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); } void grpc_cq_end_finish_accepted(grpc_completion_queue *cc, void *tag, @@ -195,11 +193,11 @@ void grpc_cq_end_finish_accepted(grpc_completion_queue *cc, void *tag, grpc_event_finish_func on_finish, void *user_data, grpc_op_error error) { event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); ev = add_locked(cc, GRPC_FINISH_ACCEPTED, tag, call, on_finish, user_data); ev->base.data.finish_accepted = error; end_op_locked(cc, GRPC_FINISH_ACCEPTED); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); } void grpc_cq_end_client_metadata_read(grpc_completion_queue *cc, void *tag, @@ -208,13 +206,13 @@ void grpc_cq_end_client_metadata_read(grpc_completion_queue *cc, void *tag, void *user_data, size_t count, grpc_metadata *elements) { event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); ev = add_locked(cc, GRPC_CLIENT_METADATA_READ, tag, call, on_finish, user_data); ev->base.data.client_metadata_read.count = count; ev->base.data.client_metadata_read.elements = elements; end_op_locked(cc, GRPC_CLIENT_METADATA_READ); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); } void grpc_cq_end_finished(grpc_completion_queue *cc, void *tag, grpc_call *call, @@ -223,14 +221,14 @@ void grpc_cq_end_finished(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_metadata *metadata_elements, size_t metadata_count) { event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); ev = add_locked(cc, GRPC_FINISHED, tag, call, on_finish, user_data); ev->base.data.finished.status = status; ev->base.data.finished.details = details; ev->base.data.finished.metadata_count = metadata_count; ev->base.data.finished.metadata_elements = metadata_elements; end_op_locked(cc, GRPC_FINISHED); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); } void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, @@ -239,7 +237,7 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, gpr_timespec deadline, size_t metadata_count, grpc_metadata *metadata_elements) { event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); ev = add_locked(cc, GRPC_SERVER_RPC_NEW, tag, call, on_finish, user_data); ev->base.data.server_rpc_new.method = method; ev->base.data.server_rpc_new.host = host; @@ -247,7 +245,7 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, ev->base.data.server_rpc_new.metadata_count = metadata_count; ev->base.data.server_rpc_new.metadata_elements = metadata_elements; end_op_locked(cc, GRPC_SERVER_RPC_NEW); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); } /* Create a GRPC_QUEUE_SHUTDOWN event without queuing it anywhere */ @@ -264,7 +262,7 @@ grpc_event *grpc_completion_queue_next(grpc_completion_queue *cc, gpr_timespec deadline) { event *ev = NULL; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); for (;;) { if (cc->queue != NULL) { gpr_uintptr bucket; @@ -290,16 +288,15 @@ grpc_event *grpc_completion_queue_next(grpc_completion_queue *cc, ev = create_shutdown_event(); break; } - if (cc->allow_polling && grpc_pollset_work(&cc->pollset, deadline)) { + if (cc->allow_polling && grpc_iomgr_work(deadline)) { continue; } - if (gpr_cv_wait(GRPC_POLLSET_CV(&cc->pollset), - GRPC_POLLSET_MU(&cc->pollset), deadline)) { - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + if (gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, deadline)) { + gpr_mu_unlock(&grpc_iomgr_mu); return NULL; } } - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ev->base); return &ev->base; } @@ -337,7 +334,7 @@ grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, gpr_timespec deadline) { event *ev = NULL; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); for (;;) { if ((ev = pluck_event(cc, tag))) { break; @@ -346,16 +343,15 @@ grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, ev = create_shutdown_event(); break; } - if (cc->allow_polling && grpc_pollset_work(&cc->pollset, deadline)) { + if (cc->allow_polling && grpc_iomgr_work(deadline)) { continue; } - if (gpr_cv_wait(GRPC_POLLSET_CV(&cc->pollset), - GRPC_POLLSET_MU(&cc->pollset), deadline)) { - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + if (gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, deadline)) { + gpr_mu_unlock(&grpc_iomgr_mu); return NULL; } } - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_unlock(&grpc_iomgr_mu); GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ev->base); return &ev->base; } @@ -364,11 +360,11 @@ grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, to zero here, then enter shutdown mode and wake up any waiters */ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) { if (gpr_unref(&cc->refs)) { - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_mu_lock(&grpc_iomgr_mu); GPR_ASSERT(!cc->shutdown); cc->shutdown = 1; - gpr_cv_broadcast(GRPC_POLLSET_CV(&cc->pollset)); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); + gpr_cv_broadcast(&grpc_iomgr_cv); + gpr_mu_unlock(&grpc_iomgr_mu); } } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index aa544a97f28..3829e7aa8f9 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -52,7 +52,7 @@ typedef enum { PENDING_START, ALL_CALLS, CALL_LIST_COUNT } call_list; typedef struct listener { void *arg; - void (*start)(grpc_server *server, void *arg, grpc_pollset *pollset); + void (*start)(grpc_server *server, void *arg); void (*destroy)(grpc_server *server, void *arg); struct listener *next; } listener; @@ -192,7 +192,7 @@ static void orphan_channel(channel_data *chand) { chand->next = chand->prev = chand; } -static void finish_destroy_channel(void *cd, int success) { +static void finish_destroy_channel(void *cd, grpc_iomgr_cb_status status) { channel_data *chand = cd; grpc_server *server = chand->server; /*gpr_log(GPR_INFO, "destroy channel %p", chand->channel);*/ @@ -247,7 +247,7 @@ static void start_new_rpc(grpc_call_element *elem) { gpr_mu_unlock(&server->mu); } -static void kill_zombie(void *elem, int success) { +static void kill_zombie(void *elem, grpc_iomgr_cb_status status) { grpc_call_destroy(grpc_call_from_top_element(elem)); } @@ -336,7 +336,7 @@ static void channel_op(grpc_channel_element *elem, } } -static void finish_shutdown_channel(void *cd, int success) { +static void finish_shutdown_channel(void *cd, grpc_iomgr_cb_status status) { channel_data *chand = cd; grpc_channel_op op; op.type = GRPC_CHANNEL_DISCONNECT; @@ -468,7 +468,7 @@ void grpc_server_start(grpc_server *server) { listener *l; for (l = server->listeners; l; l = l->next) { - l->start(server, l->arg, grpc_cq_pollset(server->cq)); + l->start(server, l->arg); } } @@ -596,8 +596,7 @@ void grpc_server_destroy(grpc_server *server) { } void grpc_server_add_listener(grpc_server *server, void *arg, - void (*start)(grpc_server *server, void *arg, - grpc_pollset *pollset), + void (*start)(grpc_server *server, void *arg), void (*destroy)(grpc_server *server, void *arg)) { listener *l = gpr_malloc(sizeof(listener)); l->arg = arg; diff --git a/src/core/surface/server.h b/src/core/surface/server.h index 61292ebe4e6..f0773ab9d57 100644 --- a/src/core/surface/server.h +++ b/src/core/surface/server.h @@ -47,8 +47,7 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, /* Add a listener to the server: when the server starts, it will call start, and when it shuts down, it will call destroy */ void grpc_server_add_listener(grpc_server *server, void *listener, - void (*start)(grpc_server *server, void *arg, - grpc_pollset *pollset), + void (*start)(grpc_server *server, void *arg), void (*destroy)(grpc_server *server, void *arg)); /* Setup a transport - creates a channel stack, binds the transport to the diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c index a0961bd4493..a5fdd037740 100644 --- a/src/core/surface/server_chttp2.c +++ b/src/core/surface/server_chttp2.c @@ -59,9 +59,9 @@ static void new_transport(void *server, grpc_endpoint *tcp) { } /* Server callback: start listening on our ports */ -static void start(grpc_server *server, void *tcpp, grpc_pollset *pollset) { +static void start(grpc_server *server, void *tcpp) { grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(tcp, pollset, new_transport, server); + grpc_tcp_server_start(tcp, new_transport, server); } /* Server callback: destroy the tcp listener (so we don't generate further diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 5bf763e76f5..a8ae8cc5bc0 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -711,7 +711,7 @@ static void unlock(transport *t) { /* write some bytes if necessary */ while (start_write) { switch (grpc_endpoint_write(ep, t->outbuf.slices, t->outbuf.count, - finish_write, t)) { + finish_write, t, gpr_inf_future)) { case GRPC_ENDPOINT_WRITE_DONE: /* grab the lock directly without wrappers since we just want to continue writes if we loop: no need to check read callbacks again */ @@ -1617,6 +1617,7 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, case GRPC_ENDPOINT_CB_SHUTDOWN: case GRPC_ENDPOINT_CB_EOF: case GRPC_ENDPOINT_CB_ERROR: + case GRPC_ENDPOINT_CB_TIMED_OUT: lock(t); drop_connection(t); t->reading = 0; @@ -1641,7 +1642,7 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, for (i = 0; i < nslices; i++) gpr_slice_unref(slices[i]); if (keep_reading) { - grpc_endpoint_notify_on_read(t->ep, recv_data, t); + grpc_endpoint_notify_on_read(t->ep, recv_data, t, gpr_inf_future); } } diff --git a/src/ruby/Gemfile b/src/ruby/Gemfile index 597a7d4f4b0..dc05f7946b2 100755 --- a/src/ruby/Gemfile +++ b/src/ruby/Gemfile @@ -1,4 +1,12 @@ source 'https://rubygems.org' +# Modify this when working locally, see README.md +# e.g, +# gem 'beefcake', path: "/usr/local/google/repos/beefcake" +# +# The default value is what's used for gRPC ruby's GCE configuration +# +gem 'beefcake', path: "/var/local/git/beefcake" + # Specify your gem's dependencies in grpc.gemspec gemspec diff --git a/src/ruby/README.md b/src/ruby/README.md index 23aec2b20af..3a5c50819b2 100755 --- a/src/ruby/README.md +++ b/src/ruby/README.md @@ -20,25 +20,67 @@ DEPENDENCIES The extension can be built and tested using [rake](https://rubygems.org/gems/rake). However, the rake-extensiontask rule is not supported on older versions of rubygems, and the necessary version of -rubygems. +rubygems is not available on the latest version of Goobuntu. This is resolved by using [RVM](https://rvm.io/) instead; install a single-user -ruby environment, and develop on the latest stable version of ruby (2.1.5). +ruby environment, and develop on the latest stable version of ruby (2.1.2). + + +* Proto code generation + +To build generate service stubs and skeletons, it's currently necessary to use +a patched version of a beefcake, a simple third-party proto2 library. This is +feature compatible with proto3 and will be replaced by official proto3 support +in protoc. + +* Patched protoc + +The patched version of beefcake in turn depends on a patched version of protoc. +This is an update of the latest open source release of protoc with some forward +looking proto3 patches. INSTALLATION PREREQUISITES -------------------------- +Install the patched protoc + +$ cd +$ git clone sso://team/one-platform-grpc-team/protobuf +$ cd protobuf +$ ./configure --prefix=/usr +$ make +$ sudo make install + +Install an update to OpenSSL with ALPN support + +$ wget https://www.openssl.org/source/openssl-1.0.2-beta3.tar.gz +$ tar -zxvf openssl-1.0.2-beta3.tar.gz +$ cd openssl-1.0.2-beta3 +$ ./config shared +$ make +$ sudo make install + Install RVM +$ # the -with-openssl-dir ensures that ruby uses the updated version of SSL $ command curl -sSL https://rvm.io/mpapis.asc | gpg --import - $ \curl -sSL https://get.rvm.io | bash -s stable --ruby $ $ # follow the instructions to ensure that your're using the latest stable version of Ruby $ # and that the rvm command is installed $ +$ rvm reinstall 2.1.5 --with-openssl-dir=/usr/local/ssl $ gem install bundler # install bundler, the standard ruby package manager +Install the patched beefcake, and update the Gemfile to reference + +$ cd +$ git clone sso://team/one-platform-grpc-team/grpc-ruby-beefcake beefcake +$ cd beefcake +$ bundle install +$ + HACKING ------- diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb index d0478bb4d1c..6e7bfeef976 100644 --- a/src/ruby/bin/interop/interop_client.rb +++ b/src/ruby/bin/interop/interop_client.rb @@ -47,11 +47,9 @@ require 'minitest' require 'minitest/assertions' require 'grpc' -require 'google/protobuf' -require 'test/cpp/interop/test_services' -require 'test/cpp/interop/messages' -require 'test/cpp/interop/empty' +require 'third_party/stubby/testing/proto/test.pb' +require 'third_party/stubby/testing/proto/messages.pb' # loads the certificates used to access the test server securely. def load_test_certs @@ -81,7 +79,7 @@ end # produces a string of null chars (\0) of length l. def nulls(l) raise 'requires #{l} to be +ve' if l < 0 - [].pack('x' * l).force_encoding('utf-8') + [].pack('x' * l) end # a PingPongPlayer implements the ping pong bidi test. @@ -107,11 +105,10 @@ class PingPongPlayer req_size, resp_size = m req = req_cls.new(:payload => Payload.new(:body => nulls(req_size)), :response_type => COMPRESSABLE, - :response_parameters => [p_cls.new(:size => resp_size)]) + :response_parameters => p_cls.new(:size => resp_size)) yield req resp = @queue.pop - assert_equal(PayloadType.lookup(COMPRESSABLE), resp.payload.type, - 'payload type is wrong') + assert_equal(COMPRESSABLE, resp.payload.type, 'payload type is wrong') assert_equal(resp_size, resp.payload.body.length, 'payload body #{i} has the wrong length') p "OK: ping_pong #{count}" @@ -135,10 +132,10 @@ class NamedTests # TESTING # PASSED # FAIL - # ruby server: fails protobuf-ruby can't pass an empty message + # ruby server: fails beefcake throws on deserializing the 0-length message def empty_unary - resp = @stub.empty_call(Empty.new) - assert resp.is_a?(Empty), 'empty_unary: invalid response' + resp = @stub.empty_call(Proto2::Empty.new) + assert resp.is_a?(Proto::Empty), 'empty_unary: invalid response' p 'OK: empty_unary' end @@ -189,8 +186,7 @@ class NamedTests resps = @stub.streaming_output_call(req) resps.each_with_index do |r, i| assert i < msg_sizes.length, 'too many responses' - assert_equal(PayloadType.lookup(COMPRESSABLE), r.payload.type, - 'payload type is wrong') + assert_equal(COMPRESSABLE, r.payload.type, 'payload type is wrong') assert_equal(msg_sizes[i], r.payload.body.length, 'payload body #{i} has the wrong length') end @@ -201,6 +197,9 @@ class NamedTests # PASSED # ruby server # FAILED + # + # TODO(temiola): update this test to stay consistent with the java test's + # interpretation of the test spec. def ping_pong msg_sizes = [[27182, 31415], [8, 9], [1828, 2653], [45904, 58979]] ppp = PingPongPlayer.new(msg_sizes) diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb index 53e271e80d5..35d69f6fd38 100644 --- a/src/ruby/bin/interop/interop_server.rb +++ b/src/ruby/bin/interop/interop_server.rb @@ -47,9 +47,8 @@ require 'optparse' require 'grpc' -require 'test/cpp/interop/test_services' -require 'test/cpp/interop/messages' -require 'test/cpp/interop/empty' +require 'third_party/stubby/testing/proto/test.pb' +require 'third_party/stubby/testing/proto/messages.pb' # loads the certificates by the test server. def load_test_certs @@ -68,7 +67,7 @@ end # produces a string of null chars (\0) of length l. def nulls(l) raise 'requires #{l} to be +ve' if l < 0 - [].pack('x' * l).force_encoding('utf-8') + [].pack('x' * l) end # A EnumeratorQueue wraps a Queue yielding the items added to it via each_item. @@ -99,7 +98,7 @@ class TestTarget < Grpc::Testing::TestService::Service include Grpc::Testing::PayloadType def empty_call(empty, call) - Empty.new + Proto::Empty.new end def unary_call(simple_req, call) diff --git a/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb b/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb new file mode 100755 index 00000000000..eadd1d4ceb5 --- /dev/null +++ b/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb @@ -0,0 +1,14 @@ +## Generated from net/proto2/bridge/proto/message_set.proto for proto2.bridge +require 'beefcake' + +module Proto2 + module Bridge + + class MessageSet + include Beefcake::Message + end + + class MessageSet + end + end +end diff --git a/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb b/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb new file mode 100755 index 00000000000..2aa0c765091 --- /dev/null +++ b/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb @@ -0,0 +1,12 @@ +## Generated from net/proto2/proto/empty.proto for proto2 +require 'beefcake' + +module Proto2 + + class Empty + include Beefcake::Message + end + + class Empty + end +end diff --git a/src/ruby/bin/interop/test/cpp/interop/empty.rb b/src/ruby/bin/interop/test/cpp/interop/empty.rb deleted file mode 100644 index acd4160d248..00000000000 --- a/src/ruby/bin/interop/test/cpp/interop/empty.rb +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: test/cpp/interop/empty.proto - -require 'google/protobuf' - -Google::Protobuf::DescriptorPool.generated_pool.build do - add_message "grpc.testing.Empty" do - end -end - -module Grpc - module Testing - Empty = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Empty").msgclass - end -end diff --git a/src/ruby/bin/interop/test/cpp/interop/messages.rb b/src/ruby/bin/interop/test/cpp/interop/messages.rb deleted file mode 100644 index 491608bff26..00000000000 --- a/src/ruby/bin/interop/test/cpp/interop/messages.rb +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: test/cpp/interop/messages.proto - -require 'google/protobuf' - -Google::Protobuf::DescriptorPool.generated_pool.build do - add_message "grpc.testing.Payload" do - optional :type, :enum, 1, "grpc.testing.PayloadType" - optional :body, :string, 2 - end - add_message "grpc.testing.SimpleRequest" do - optional :response_type, :enum, 1, "grpc.testing.PayloadType" - optional :response_size, :int32, 2 - optional :payload, :message, 3, "grpc.testing.Payload" - end - add_message "grpc.testing.SimpleResponse" do - optional :payload, :message, 1, "grpc.testing.Payload" - optional :effective_gaia_user_id, :int64, 2 - end - add_message "grpc.testing.StreamingInputCallRequest" do - optional :payload, :message, 1, "grpc.testing.Payload" - end - add_message "grpc.testing.StreamingInputCallResponse" do - optional :aggregated_payload_size, :int32, 1 - end - add_message "grpc.testing.ResponseParameters" do - optional :size, :int32, 1 - optional :interval_us, :int32, 2 - end - add_message "grpc.testing.StreamingOutputCallRequest" do - optional :response_type, :enum, 1, "grpc.testing.PayloadType" - repeated :response_parameters, :message, 2, "grpc.testing.ResponseParameters" - optional :payload, :message, 3, "grpc.testing.Payload" - end - add_message "grpc.testing.StreamingOutputCallResponse" do - optional :payload, :message, 1, "grpc.testing.Payload" - end - add_enum "grpc.testing.PayloadType" do - value :COMPRESSABLE, 0 - value :UNCOMPRESSABLE, 1 - value :RANDOM, 2 - end -end - -module Grpc - module Testing - Payload = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Payload").msgclass - SimpleRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleRequest").msgclass - SimpleResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleResponse").msgclass - StreamingInputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallRequest").msgclass - StreamingInputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallResponse").msgclass - ResponseParameters = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ResponseParameters").msgclass - StreamingOutputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallRequest").msgclass - StreamingOutputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallResponse").msgclass - PayloadType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.PayloadType").enummodule - end -end diff --git a/src/ruby/bin/interop/test/cpp/interop/test.rb b/src/ruby/bin/interop/test/cpp/interop/test.rb deleted file mode 100644 index 0b391ed6af0..00000000000 --- a/src/ruby/bin/interop/test/cpp/interop/test.rb +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: test/cpp/interop/test.proto - -require 'google/protobuf' - -require 'test/cpp/interop/empty' -require 'test/cpp/interop/messages' -Google::Protobuf::DescriptorPool.generated_pool.build do -end - -module Grpc - module Testing - end -end diff --git a/src/ruby/bin/interop/test/cpp/interop/test_services.rb b/src/ruby/bin/interop/test/cpp/interop/test_services.rb deleted file mode 100644 index 17b5461d3e3..00000000000 --- a/src/ruby/bin/interop/test/cpp/interop/test_services.rb +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# Source: test/cpp/interop/test.proto for package 'grpc.testing' - -require 'grpc' -require 'test/cpp/interop/test' - -module Grpc - module Testing - module TestService - - # TODO: add proto service documentation here - class Service - - include GRPC::GenericService - - self.marshal_class_method = :encode - self.unmarshal_class_method = :decode - self.service_name = 'grpc.testing.TestService' - - rpc :EmptyCall, Empty, Empty - rpc :UnaryCall, SimpleRequest, SimpleResponse - rpc :StreamingOutputCall, StreamingOutputCallRequest, stream(StreamingOutputCallResponse) - rpc :StreamingInputCall, stream(StreamingInputCallRequest), StreamingInputCallResponse - rpc :FullDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) - rpc :HalfDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) - end - - Stub = Service.rpc_stub_class - end - end -end diff --git a/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb b/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb new file mode 100755 index 00000000000..9a913f93e58 --- /dev/null +++ b/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb @@ -0,0 +1,94 @@ +## Generated from third_party/stubby/testing/proto/messages.proto for grpc.testing +require 'beefcake' + +require 'net/proto2/bridge/proto/message_set.pb' + +module Grpc + module Testing + + module PayloadType + COMPRESSABLE = 0 + UNCOMPRESSABLE = 1 + RANDOM = 2 + end + + class Payload + include Beefcake::Message + end + + class SimpleRequest + include Beefcake::Message + end + + class SimpleResponse + include Beefcake::Message + end + + class SimpleContext + include Beefcake::Message + end + + class StreamingInputCallRequest + include Beefcake::Message + end + + class StreamingInputCallResponse + include Beefcake::Message + end + + class ResponseParameters + include Beefcake::Message + end + + class StreamingOutputCallRequest + include Beefcake::Message + end + + class StreamingOutputCallResponse + include Beefcake::Message + end + + class Payload + optional :type, PayloadType, 1 + optional :body, :bytes, 2 + end + + class SimpleRequest + optional :response_type, PayloadType, 1 + optional :response_size, :int32, 2 + optional :payload, Payload, 3 + end + + class SimpleResponse + optional :payload, Payload, 1 + optional :effective_gaia_user_id, :int64, 2 + end + + class SimpleContext + optional :value, :string, 1 + end + + class StreamingInputCallRequest + optional :payload, Payload, 1 + end + + class StreamingInputCallResponse + optional :aggregated_payload_size, :int32, 1 + end + + class ResponseParameters + optional :size, :int32, 1 + optional :interval_us, :int32, 2 + end + + class StreamingOutputCallRequest + optional :response_type, PayloadType, 1 + repeated :response_parameters, ResponseParameters, 2 + optional :payload, Payload, 3 + end + + class StreamingOutputCallResponse + optional :payload, Payload, 1 + end + end +end diff --git a/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb b/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb new file mode 100755 index 00000000000..2e21460fe65 --- /dev/null +++ b/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb @@ -0,0 +1,30 @@ +## Generated from third_party/stubby/testing/proto/test.proto for grpc.testing +require 'beefcake' +require 'grpc' + +require 'third_party/stubby/testing/proto/messages.pb' +require 'net/proto2/proto/empty.pb' + +module Grpc + module Testing + + module TestService + + class Service + include GRPC::GenericService + + self.marshal_class_method = :encode + self.unmarshal_class_method = :decode + + rpc :EmptyCall, Proto2::Empty, Proto2::Empty + rpc :UnaryCall, SimpleRequest, SimpleResponse + rpc :StreamingOutputCall, StreamingOutputCallRequest, stream(StreamingOutputCallResponse) + rpc :StreamingInputCall, stream(StreamingInputCallRequest), StreamingInputCallResponse + rpc :FullDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) + rpc :HalfDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) + end + Stub = Service.rpc_stub_class + + end + end +end diff --git a/src/ruby/bin/math.pb.rb b/src/ruby/bin/math.pb.rb new file mode 100755 index 00000000000..f6976be5684 --- /dev/null +++ b/src/ruby/bin/math.pb.rb @@ -0,0 +1,65 @@ +## Generated from bin/math.proto for math +require "beefcake" +require "grpc" + +module Math + + class DivArgs + include Beefcake::Message + end + + class DivReply + include Beefcake::Message + end + + class FibArgs + include Beefcake::Message + end + + class Num + include Beefcake::Message + end + + class FibReply + include Beefcake::Message + end + + class DivArgs + required :dividend, :int64, 1 + required :divisor, :int64, 2 + end + + class DivReply + required :quotient, :int64, 1 + required :remainder, :int64, 2 + end + + class FibArgs + optional :limit, :int64, 1 + end + + class Num + required :num, :int64, 1 + end + + class FibReply + required :count, :int64, 1 + end + + module Math + + class Service + include GRPC::GenericService + + self.marshal_class_method = :encode + self.unmarshal_class_method = :decode + + rpc :Div, DivArgs, DivReply + rpc :DivMany, stream(DivArgs), stream(DivReply) + rpc :Fib, FibArgs, stream(Num) + rpc :Sum, stream(Num), Num + end + Stub = Service.rpc_stub_class + + end +end diff --git a/src/ruby/bin/math.proto b/src/ruby/bin/math.proto index c49787ad54d..de18a502602 100755 --- a/src/ruby/bin/math.proto +++ b/src/ruby/bin/math.proto @@ -1,15 +1,15 @@ -syntax = "proto3"; +syntax = "proto2"; package math; message DivArgs { - optional int64 dividend = 1; - optional int64 divisor = 2; + required int64 dividend = 1; + required int64 divisor = 2; } message DivReply { - optional int64 quotient = 1; - optional int64 remainder = 2; + required int64 quotient = 1; + required int64 remainder = 2; } message FibArgs { @@ -17,11 +17,11 @@ message FibArgs { } message Num { - optional int64 num = 1; + required int64 num = 1; } message FibReply { - optional int64 count = 1; + required int64 count = 1; } service Math { diff --git a/src/ruby/bin/math.rb b/src/ruby/bin/math.rb deleted file mode 100644 index 09d1e985864..00000000000 --- a/src/ruby/bin/math.rb +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: math.proto - -require 'google/protobuf' - -Google::Protobuf::DescriptorPool.generated_pool.build do - add_message "math.DivArgs" do - optional :dividend, :int64, 1 - optional :divisor, :int64, 2 - end - add_message "math.DivReply" do - optional :quotient, :int64, 1 - optional :remainder, :int64, 2 - end - add_message "math.FibArgs" do - optional :limit, :int64, 1 - end - add_message "math.Num" do - optional :num, :int64, 1 - end - add_message "math.FibReply" do - optional :count, :int64, 1 - end -end - -module Math - DivArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.DivArgs").msgclass - DivReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.DivReply").msgclass - FibArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.FibArgs").msgclass - Num = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.Num").msgclass - FibReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.FibReply").msgclass -end diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb index 5cba9317f4f..8a62764c084 100644 --- a/src/ruby/bin/math_client.rb +++ b/src/ruby/bin/math_client.rb @@ -40,7 +40,7 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' -require 'math_services' +require 'math.pb' require 'optparse' include GRPC::Core::TimeConsts @@ -111,8 +111,8 @@ def main 'secure' => false } OptionParser.new do |opts| - opts.banner = 'Usage: [--host :] [--secure|-s]' - opts.on('--host HOST', ':') do |v| + opts.banner = 'Usage: [--host|-h :] [--secure|-s]' + opts.on('-h', '--host', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb index a0f301c3e79..ed39144d7aa 100644 --- a/src/ruby/bin/math_server.rb +++ b/src/ruby/bin/math_server.rb @@ -41,7 +41,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'forwardable' require 'grpc' -require 'math_services' +require 'math.pb' require 'optparse' # Holds state for a fibonacci series @@ -168,8 +168,8 @@ def main 'secure' => false } OptionParser.new do |opts| - opts.banner = 'Usage: [--host :] [--secure|-s]' - opts.on('--host HOST', ':') do |v| + opts.banner = 'Usage: [--host|-h :] [--secure|-s]' + opts.on('-h', '--host', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| diff --git a/src/ruby/bin/math_services.rb b/src/ruby/bin/math_services.rb deleted file mode 100644 index f6ca6fe060c..00000000000 --- a/src/ruby/bin/math_services.rb +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# Source: math.proto for package 'math' - -require 'grpc' -require 'math' - -module Math - module Math - - # TODO: add proto service documentation here - class Service - - include GRPC::GenericService - - self.marshal_class_method = :encode - self.unmarshal_class_method = :decode - self.service_name = 'math.Math' - - rpc :Div, DivArgs, DivReply - rpc :DivMany, stream(DivArgs), stream(DivReply) - rpc :Fib, FibArgs, stream(Num) - rpc :Sum, stream(Num), Num - end - - Stub = Service.rpc_stub_class - end -end diff --git a/src/ruby/bin/noproto_client.rb b/src/ruby/bin/noproto_client.rb index 50ae9fb68f8..29ed6d9f7cc 100644 --- a/src/ruby/bin/noproto_client.rb +++ b/src/ruby/bin/noproto_client.rb @@ -37,68 +37,36 @@ lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' -require 'optparse' -class NoProtoMsg - def self.marshal(o) +class EchoMsg + def marshal '' end def self.unmarshal(o) - NoProtoMsg.new + EchoMsg.new end end -class NoProtoService +class EchoService include GRPC::GenericService - rpc :AnRPC, NoProtoMsg, NoProtoMsg -end + rpc :AnRPC, EchoMsg, EchoMsg -NoProtoStub = NoProtoService.rpc_stub_class + def initialize(default_var='ignored') + end -def load_test_certs - this_dir = File.expand_path(File.dirname(__FILE__)) - data_dir = File.join(File.dirname(this_dir), 'spec/testdata') - files = ['ca.pem', 'server1.key', 'server1.pem'] - files.map { |f| File.open(File.join(data_dir, f)).read } + def an_rpc(req, call) + logger.info('echo service received a request') + req + end end -def test_creds - certs = load_test_certs - creds = GRPC::Core::Credentials.new(certs[0]) -end +EchoStub = EchoService.rpc_stub_class def main - options = { - 'host' => 'localhost:7071', - 'secure' => false - } - OptionParser.new do |opts| - opts.banner = 'Usage: [--host :] [--secure|-s]' - opts.on('--host HOST', ':') do |v| - options['host'] = v - end - opts.on('-s', '--secure', 'access using test creds') do |v| - options['secure'] = true - end - end.parse! - - if options['secure'] - stub_opts = { - :creds => test_creds, - GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', - } - p stub_opts - p options['host'] - stub = NoProtoStub.new(options['host'], **stub_opts) - logger.info("... connecting securely on #{options['host']}") - else - stub = NoProtoStub.new(options['host']) - logger.info("... connecting insecurely on #{options['host']}") - end - - logger.info('sending a NoProto rpc') - resp = stub.an_rpc(NoProtoMsg.new) + stub = EchoStub.new('localhost:9090') + logger.info('sending an rpc') + resp = stub.an_rpc(EchoMsg.new) logger.info("got a response: #{resp}") end diff --git a/src/ruby/bin/noproto_server.rb b/src/ruby/bin/noproto_server.rb index d410827b22d..7b74fa13ec2 100644 --- a/src/ruby/bin/noproto_server.rb +++ b/src/ruby/bin/noproto_server.rb @@ -37,24 +37,23 @@ lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' -require 'optparse' -class NoProtoMsg - def self.marshal(o) +class EchoMsg + def marshal '' end def self.unmarshal(o) - NoProtoMsg.new + EchoMsg.new end end -class NoProtoService +class EchoService include GRPC::GenericService - rpc :AnRPC, NoProtoMsg, NoProtoMsg + rpc :AnRPC, EchoMsg, EchoMsg end -class NoProto < NoProtoService +class Echo < EchoService def initialize(default_var='ignored') end @@ -64,46 +63,11 @@ class NoProto < NoProtoService end end -def load_test_certs - this_dir = File.expand_path(File.dirname(__FILE__)) - data_dir = File.join(File.dirname(this_dir), 'spec/testdata') - files = ['ca.pem', 'server1.key', 'server1.pem'] - files.map { |f| File.open(File.join(data_dir, f)).read } -end - -def test_server_creds - certs = load_test_certs - server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) -end - def main - options = { - 'host' => 'localhost:9090', - 'secure' => false - } - OptionParser.new do |opts| - opts.banner = 'Usage: [--host :] [--secure|-s]' - opts.on('--host HOST', ':') do |v| - options['host'] = v - end - opts.on('-s', '--secure', 'access using test creds') do |v| - options['secure'] = true - end - end.parse! - - if options['secure'] - s = GRPC::RpcServer.new(creds: test_server_creds) - s.add_http2_port(options['host'], true) - logger.info("... running securely on #{options['host']}") - else - s = GRPC::RpcServer.new - s.add_http2_port(options['host']) - logger.info("... running insecurely on #{options['host']}") - end - - s.handle(NoProto) + s = GRPC::RpcServer.new() + s.add_http2_port('localhost:9090') + s.handle(Echo) s.run end - main diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec index 3e1dcd578b6..b535de49467 100755 --- a/src/ruby/grpc.gemspec +++ b/src/ruby/grpc.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency 'xray' s.add_dependency 'logging', '~> 1.8' - s.add_dependency 'google-protobuf', '~> 3.0.0alpha' + s.add_dependency 'beefcake', '~> 1.1' s.add_dependency 'minitest', '~> 5.4' # not a dev dependency, used by the interop tests s.add_development_dependency "bundler", "~> 1.7" diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index 81c67ec8592..c7eec3388c8 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -27,6 +27,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +require 'grpc/beefcake' # extends beefcake require 'grpc/errors' require 'grpc/grpc' require 'grpc/logconfig' diff --git a/src/ruby/lib/grpc/generic/service.rb b/src/ruby/lib/grpc/generic/service.rb index f3fe638fcef..6a4356fab9e 100644 --- a/src/ruby/lib/grpc/generic/service.rb +++ b/src/ruby/lib/grpc/generic/service.rb @@ -93,8 +93,6 @@ module Google::RPC # The Dsl verifies that the types in the descriptor have both the # unmarshal and marshal methods. attr_writer(:marshal_class_method, :unmarshal_class_method) - - # This allows configuration of the service name. attr_accessor(:service_name) # Adds an RPC spec. @@ -119,8 +117,8 @@ module Google::RPC end def inherited(subclass) - # Each subclass should have a distinct class variable with its own - # rpc_descs + # Each subclass should have distinct class variable with its own + # rpc_descs. subclass.rpc_descs.merge!(rpc_descs) subclass.service_name = service_name end @@ -229,9 +227,8 @@ module Google::RPC def self.included(o) o.extend(Dsl) - # Update to the use the service name including module. Proivde a default - # that can be nil e,g. when modules are declared dynamically. - return unless o.service_name.nil? + # Update to the use the name including module. This can be nil e,g. when + # modules are declared dynamically. if o.name.nil? o.service_name = 'GenericService' else diff --git a/src/ruby/spec/generic/service_spec.rb b/src/ruby/spec/generic/service_spec.rb index a8e0c6f52fe..dc921d89345 100644 --- a/src/ruby/spec/generic/service_spec.rb +++ b/src/ruby/spec/generic/service_spec.rb @@ -108,39 +108,6 @@ describe GenericService do expect(c.rpc_descs[:AnRpc]).to be_a(GRPC::RpcDesc) end - it 'adds a default service name' do - c = Class.new do - include GenericService - end - expect(c.service_name).to eq('GenericService') - end - - it 'adds a default service name to subclasses' do - base = Class.new do - include GenericService - end - c = Class.new(base) do - end - expect(c.service_name).to eq('GenericService') - end - - it 'adds the specified service name' do - c = Class.new do - include GenericService - self.service_name = 'test.service.TestService' - end - expect(c.service_name).to eq('test.service.TestService') - end - - it 'adds the specified service name to subclasses' do - base = Class.new do - include GenericService - self.service_name = 'test.service.TestService' - end - c = Class.new(base) do - end - expect(c.service_name).to eq('test.service.TestService') - end end describe '#include' do diff --git a/templates/Makefile.template b/templates/Makefile.template index 44144c8f7e5..bdb97651145 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -100,7 +100,7 @@ CPPFLAGS += -g -fPIC -Wall -Werror -Wno-long-long LDFLAGS += -g -pthread -fPIC INCLUDES = . include gens -LIBS = rt m z pthread +LIBS = rt m z event event_pthreads pthread LIBSXX = protobuf LIBS_PROTOC = protoc protobuf @@ -159,12 +159,20 @@ else IS_GIT_FOLDER = true endif +EVENT2_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/event2.c -levent $(LDFLAGS) OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS) ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) +HAS_SYSTEM_EVENT2 = $(shell $(EVENT2_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false) +ifeq ($(wildcard third_party/libevent/include/event2/event.h),) +HAS_EMBEDDED_EVENT2 = false +else +HAS_EMBEDDED_EVENT2 = true +endif + ifeq ($(wildcard third_party/openssl/ssl/ssl.h),) HAS_EMBEDDED_OPENSSL_ALPN = false else @@ -177,6 +185,12 @@ else HAS_EMBEDDED_ZLIB = true endif +ifneq ($(SYSTEM),MINGW32) +ifeq ($(HAS_SYSTEM_EVENT2),false) +DEP_MISSING += libevent +endif +endif + ifeq ($(HAS_SYSTEM_ZLIB),false) ifeq ($(HAS_EMBEDDED_ZLIB),true) ZLIB_DEP = third_party/zlib/libz.a @@ -277,6 +291,7 @@ ${tgt.name}: bins/$(CONFIG)/${tgt.name} % endfor run_dep_checks: + $(EVENT2_CHECK_CMD) || true $(OPENSSL_ALPN_CHECK_CMD) || true $(ZLIB_CHECK_CMD) || true diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c index e5b7304743f..1181f1b4de9 100644 --- a/test/core/end2end/cq_verifier.c +++ b/test/core/end2end/cq_verifier.c @@ -371,12 +371,7 @@ void cq_verify_empty(cq_verifier *v) { GPR_ASSERT(v->expect.next == &v->expect && "expectation queue must be empty"); ev = grpc_completion_queue_next(v->cq, deadline); - if (ev != NULL) { - char *s = grpc_event_string(ev); - gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s", s); - gpr_free(s); - abort(); - } + GPR_ASSERT(ev == NULL); } static expectation *add(cq_verifier *v, grpc_completion_type type, void *tag) { diff --git a/test/core/end2end/fixtures/chttp2_socket_pair.c b/test/core/end2end/fixtures/chttp2_socket_pair.c index cb5c6f7cad8..b3fac796f4c 100644 --- a/test/core/end2end/fixtures/chttp2_socket_pair.c +++ b/test/core/end2end/fixtures/chttp2_socket_pair.c @@ -120,7 +120,6 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, GPR_ASSERT(!f->server); f->server = grpc_server_create_from_filters(f->server_cq, NULL, 0, server_args); - grpc_server_start(f->server); grpc_create_chttp2_transport(server_setup_transport, f, server_args, sfd->server, NULL, 0, grpc_mdctx_create(), 0); } diff --git a/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c b/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c index 84acfa6d6cd..061e049a09d 100644 --- a/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c +++ b/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c @@ -120,7 +120,6 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, GPR_ASSERT(!f->server); f->server = grpc_server_create_from_filters(f->server_cq, NULL, 0, server_args); - grpc_server_start(f->server); grpc_create_chttp2_transport(server_setup_transport, f, server_args, sfd->server, NULL, 0, grpc_mdctx_create(), 0); } diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c index bad86fb9dcd..d15fef6adc1 100644 --- a/test/core/end2end/tests/invoke_large_request.c +++ b/test/core/end2end/tests/invoke_large_request.c @@ -112,7 +112,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { gpr_slice request_payload_slice = large_slice(); grpc_byte_buffer *request_payload = grpc_byte_buffer_create(&request_payload_slice, 1); - gpr_timespec deadline = n_seconds_time(30); + gpr_timespec deadline = n_seconds_time(10); grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL); cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index a418d1b15f3..08198d49fbd 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -156,12 +156,9 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { grpc_call *c2; grpc_call *s1; grpc_call *s2; - int live_call; - grpc_call *live_call_obj; gpr_timespec deadline; cq_verifier *v_client; cq_verifier *v_server; - grpc_event *ev; server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS; server_arg.type = GRPC_ARG_INTEGER; @@ -183,10 +180,9 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* start two requests - ensuring that the second is not accepted until the first completes */ deadline = five_seconds_time(); - c1 = - grpc_channel_create_call(f.client, "/alpha", "test.google.com", deadline); + c1 = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c1); - c2 = grpc_channel_create_call(f.client, "/beta", "test.google.com", deadline); + c2 = grpc_channel_create_call(f.client, "/bar", "test.google.com", deadline); GPR_ASSERT(c1); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); @@ -195,29 +191,19 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { tag(301), tag(302), 0)); GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_invoke(c2, f.client_cq, tag(400), tag(401), tag(402), 0)); - ev = grpc_completion_queue_next( - f.client_cq, gpr_time_add(gpr_now(), gpr_time_from_seconds(10))); - GPR_ASSERT(ev); - GPR_ASSERT(ev->type == GRPC_INVOKE_ACCEPTED); - GPR_ASSERT(ev->data.invoke_accepted == GRPC_OP_OK); - /* The /alpha or /beta calls started above could be invoked (but NOT both); - * check this here */ - live_call = (int)(gpr_intptr)ev->tag; - live_call_obj = live_call == 300 ? c1 : c2; - grpc_event_finish(ev); + cq_expect_invoke_accepted(v_client, tag(300), GRPC_OP_OK); + cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == - grpc_call_writes_done(live_call_obj, tag(live_call + 3))); - cq_expect_finish_accepted(v_client, tag(live_call + 3), GRPC_OP_OK); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c1, tag(303))); + cq_expect_finish_accepted(v_client, tag(303), GRPC_OP_OK); cq_verify(v_client); - cq_expect_server_rpc_new(v_server, &s1, tag(100), - live_call == 300 ? "/alpha" : "/beta", - "test.google.com", deadline, NULL); + cq_expect_server_rpc_new(v_server, &s1, tag(100), "/foo", "test.google.com", + deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == grpc_call_accept(s1, f.server_cq, tag(102), 0)); - cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL); + cq_expect_client_metadata_read(v_client, tag(301), NULL); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == @@ -228,26 +214,22 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { cq_verify(v_server); /* first request is finished, we should be able to start the second */ - cq_expect_finished_with_status(v_client, tag(live_call + 2), - GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); - live_call = (live_call == 300) ? 400 : 300; - live_call_obj = live_call == 300 ? c1 : c2; - cq_expect_invoke_accepted(v_client, tag(live_call), GRPC_OP_OK); + cq_expect_finished_with_status(v_client, tag(302), GRPC_STATUS_UNIMPLEMENTED, + "xyz", NULL); + cq_expect_invoke_accepted(v_client, tag(400), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == - grpc_call_writes_done(live_call_obj, tag(live_call + 3))); - cq_expect_finish_accepted(v_client, tag(live_call + 3), GRPC_OP_OK); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c2, tag(403))); + cq_expect_finish_accepted(v_client, tag(403), GRPC_OP_OK); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(200))); - cq_expect_server_rpc_new(v_server, &s2, tag(200), - live_call == 300 ? "/alpha" : "/beta", - "test.google.com", deadline, NULL); + cq_expect_server_rpc_new(v_server, &s2, tag(200), "/bar", "test.google.com", + deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == grpc_call_accept(s2, f.server_cq, tag(202), 0)); - cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL); + cq_expect_client_metadata_read(v_client, tag(401), NULL); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == @@ -257,8 +239,8 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { cq_expect_finished(v_server, tag(202), NULL); cq_verify(v_server); - cq_expect_finished_with_status(v_client, tag(live_call + 2), - GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); + cq_expect_finished_with_status(v_client, tag(402), GRPC_STATUS_UNIMPLEMENTED, + "xyz", NULL); cq_verify(v_client); cq_verifier_destroy(v_client); diff --git a/test/core/iomgr/alarm_list_test.c b/test/core/iomgr/alarm_list_test.c index 686d21d705a..a8aa6126e62 100644 --- a/test/core/iomgr/alarm_list_test.c +++ b/test/core/iomgr/alarm_list_test.c @@ -41,13 +41,13 @@ #define MAX_CB 30 -static int cb_called[MAX_CB][2]; +static int cb_called[MAX_CB][GRPC_CALLBACK_DO_NOT_USE]; static int kicks; void grpc_kick_poller() { ++kicks; } -static void cb(void *arg, int success) { - cb_called[(gpr_intptr)arg][success]++; +static void cb(void *arg, grpc_iomgr_cb_status status) { + cb_called[(gpr_intptr)arg][status]++; } static void add_test() { @@ -72,36 +72,36 @@ static void add_test() { /* collect alarms. Only the first batch should be ready. */ GPR_ASSERT(10 == - grpc_alarm_check( - NULL, gpr_time_add(start, gpr_time_from_millis(500)), NULL)); + grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(500)))); for (i = 0; i < 20; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 10)); - GPR_ASSERT(cb_called[i][0] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 10)); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); } GPR_ASSERT(0 == - grpc_alarm_check( - NULL, gpr_time_add(start, gpr_time_from_millis(600)), NULL)); + grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(600)))); for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 10)); - GPR_ASSERT(cb_called[i][0] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 10)); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); } /* collect the rest of the alarms */ GPR_ASSERT(10 == - grpc_alarm_check( - NULL, gpr_time_add(start, gpr_time_from_millis(1500)), NULL)); + grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(1500)))); for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 20)); - GPR_ASSERT(cb_called[i][0] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 20)); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); } GPR_ASSERT(0 == - grpc_alarm_check( - NULL, gpr_time_add(start, gpr_time_from_millis(1600)), NULL)); + grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(1600)))); for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][1] == (i < 20)); - GPR_ASSERT(cb_called[i][0] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 20)); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); + GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); } grpc_alarm_list_shutdown(); @@ -124,16 +124,16 @@ void destruction_test() { (void *)(gpr_intptr)3, gpr_time_0); grpc_alarm_init(&alarms[4], gpr_time_from_millis(1), cb, (void *)(gpr_intptr)4, gpr_time_0); - GPR_ASSERT(1 == grpc_alarm_check(NULL, gpr_time_from_millis(2), NULL)); - GPR_ASSERT(1 == cb_called[4][1]); + GPR_ASSERT(1 == grpc_alarm_check(gpr_time_from_millis(2))); + GPR_ASSERT(1 == cb_called[4][GRPC_CALLBACK_SUCCESS]); grpc_alarm_cancel(&alarms[0]); grpc_alarm_cancel(&alarms[3]); - GPR_ASSERT(1 == cb_called[0][0]); - GPR_ASSERT(1 == cb_called[3][0]); + GPR_ASSERT(1 == cb_called[0][GRPC_CALLBACK_CANCELLED]); + GPR_ASSERT(1 == cb_called[3][GRPC_CALLBACK_CANCELLED]); grpc_alarm_list_shutdown(); - GPR_ASSERT(1 == cb_called[1][0]); - GPR_ASSERT(1 == cb_called[2][0]); + GPR_ASSERT(1 == cb_called[1][GRPC_CALLBACK_CANCELLED]); + GPR_ASSERT(1 == cb_called[2][GRPC_CALLBACK_CANCELLED]); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/alarm_test.c b/test/core/iomgr/alarm_test.c index 247320de04f..271c42d57e2 100644 --- a/test/core/iomgr/alarm_test.c +++ b/test/core/iomgr/alarm_test.c @@ -51,10 +51,8 @@ #include #include "test/core/util/test_config.h" -#define SUCCESS_NOT_SET (-1) - /* Dummy gRPC callback */ -void no_op_cb(void *arg, int success) {} +void no_op_cb(void *arg, grpc_iomgr_cb_status status) {} typedef struct { gpr_cv cv; @@ -64,25 +62,27 @@ typedef struct { int done_cancel_ctr; int done; gpr_event fcb_arg; - int success; + grpc_iomgr_cb_status status; } alarm_arg; -static void followup_cb(void *arg, int success) { +static void followup_cb(void *arg, grpc_iomgr_cb_status status) { gpr_event_set((gpr_event *)arg, arg); } /* Called when an alarm expires. */ -static void alarm_cb(void *arg /* alarm_arg */, int success) { +static void alarm_cb(void *arg /* alarm_arg */, grpc_iomgr_cb_status status) { alarm_arg *a = arg; gpr_mu_lock(&a->mu); - if (success) { + if (status == GRPC_CALLBACK_SUCCESS) { a->counter++; a->done_success_ctr++; - } else { + } else if (status == GRPC_CALLBACK_CANCELLED) { a->done_cancel_ctr++; + } else { + GPR_ASSERT(0); } a->done = 1; - a->success = success; + a->status = status; gpr_cv_signal(&a->cv); gpr_mu_unlock(&a->mu); grpc_iomgr_add_callback(followup_cb, &a->fcb_arg); @@ -105,7 +105,7 @@ static void test_grpc_alarm() { grpc_iomgr_init(); arg.counter = 0; - arg.success = SUCCESS_NOT_SET; + arg.status = GRPC_CALLBACK_DO_NOT_USE; arg.done_success_ctr = 0; arg.done_cancel_ctr = 0; arg.done = 0; @@ -138,7 +138,7 @@ static void test_grpc_alarm() { } else if (arg.done_cancel_ctr != 0) { gpr_log(GPR_ERROR, "Alarm done callback called with cancel"); GPR_ASSERT(0); - } else if (arg.success == SUCCESS_NOT_SET) { + } else if (arg.status == GRPC_CALLBACK_DO_NOT_USE) { gpr_log(GPR_ERROR, "Alarm callback without status"); GPR_ASSERT(0); } else { @@ -154,7 +154,7 @@ static void test_grpc_alarm() { gpr_mu_destroy(&arg.mu); arg2.counter = 0; - arg2.success = SUCCESS_NOT_SET; + arg2.status = GRPC_CALLBACK_DO_NOT_USE; arg2.done_success_ctr = 0; arg2.done_cancel_ctr = 0; arg2.done = 0; @@ -188,7 +188,7 @@ static void test_grpc_alarm() { } else if (arg2.done_cancel_ctr + arg2.done_success_ctr != 1) { gpr_log(GPR_ERROR, "Alarm done callback called incorrect number of times"); GPR_ASSERT(0); - } else if (arg2.success == SUCCESS_NOT_SET) { + } else if (arg2.status == GRPC_CALLBACK_DO_NOT_USE) { gpr_log(GPR_ERROR, "Alarm callback without status"); GPR_ASSERT(0); } else if (arg2.done_success_ctr) { diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c index 125cde46785..6a7f6afbc6b 100644 --- a/test/core/iomgr/endpoint_tests.c +++ b/test/core/iomgr/endpoint_tests.c @@ -145,8 +145,8 @@ static void read_and_write_test_read_handler(void *data, gpr_slice *slices, gpr_cv_signal(&state->cv); gpr_mu_unlock(&state->mu); } else { - grpc_endpoint_notify_on_read(state->read_ep, - read_and_write_test_read_handler, data); + grpc_endpoint_notify_on_read( + state->read_ep, read_and_write_test_read_handler, data, gpr_inf_future); } } @@ -159,8 +159,6 @@ static void read_and_write_test_write_handler(void *data, GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); - gpr_log(GPR_DEBUG, "%s: error=%d", __FUNCTION__, error); - if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { gpr_log(GPR_INFO, "Write handler shutdown"); gpr_mu_lock(&state->mu); @@ -184,10 +182,9 @@ static void read_and_write_test_write_handler(void *data, slices = allocate_blocks(state->current_write_size, 8192, &nslices, &state->current_write_data); - write_status = - grpc_endpoint_write(state->write_ep, slices, nslices, - read_and_write_test_write_handler, state); - gpr_log(GPR_DEBUG, "write_status=%d", write_status); + write_status = grpc_endpoint_write(state->write_ep, slices, nslices, + read_and_write_test_write_handler, state, + gpr_inf_future); GPR_ASSERT(write_status != GRPC_ENDPOINT_WRITE_ERROR); free(slices); if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { @@ -211,7 +208,8 @@ static void read_and_write_test(grpc_endpoint_test_config config, size_t num_bytes, size_t write_size, size_t slice_size, int shutdown) { struct read_and_write_test_state state; - gpr_timespec deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(20)); + gpr_timespec rel_deadline = {20, 0}; + gpr_timespec deadline = gpr_time_add(gpr_now(), rel_deadline); grpc_endpoint_test_fixture f = begin_test(config, __FUNCTION__, slice_size); if (shutdown) { @@ -243,22 +241,16 @@ static void read_and_write_test(grpc_endpoint_test_config config, read_and_write_test_write_handler(&state, GRPC_ENDPOINT_CB_OK); grpc_endpoint_notify_on_read(state.read_ep, read_and_write_test_read_handler, - &state); + &state, gpr_inf_future); if (shutdown) { - gpr_log(GPR_DEBUG, "shutdown read"); grpc_endpoint_shutdown(state.read_ep); - gpr_log(GPR_DEBUG, "shutdown write"); grpc_endpoint_shutdown(state.write_ep); } gpr_mu_lock(&state.mu); while (!state.read_done || !state.write_done) { - if (gpr_cv_wait(&state.cv, &state.mu, deadline)) { - gpr_log(GPR_ERROR, "timeout: read_done=%d, write_done=%d", - state.read_done, state.write_done); - abort(); - } + GPR_ASSERT(gpr_cv_wait(&state.cv, &state.mu, deadline) == 0); } gpr_mu_unlock(&state.mu); @@ -273,6 +265,79 @@ struct timeout_test_state { gpr_event io_done; }; +static void read_timeout_test_read_handler(void *data, gpr_slice *slices, + size_t nslices, + grpc_endpoint_cb_status error) { + struct timeout_test_state *state = data; + GPR_ASSERT(error == GRPC_ENDPOINT_CB_TIMED_OUT); + gpr_event_set(&state->io_done, (void *)1); +} + +static void read_timeout_test(grpc_endpoint_test_config config, + size_t slice_size) { + gpr_timespec timeout = gpr_time_from_micros(10000); + gpr_timespec read_deadline = gpr_time_add(gpr_now(), timeout); + gpr_timespec test_deadline = + gpr_time_add(gpr_now(), gpr_time_from_micros(2000000)); + struct timeout_test_state state; + grpc_endpoint_test_fixture f = begin_test(config, __FUNCTION__, slice_size); + + gpr_event_init(&state.io_done); + + grpc_endpoint_notify_on_read(f.client_ep, read_timeout_test_read_handler, + &state, read_deadline); + GPR_ASSERT(gpr_event_wait(&state.io_done, test_deadline)); + grpc_endpoint_destroy(f.client_ep); + grpc_endpoint_destroy(f.server_ep); + end_test(config); +} + +static void write_timeout_test_write_handler(void *data, + grpc_endpoint_cb_status error) { + struct timeout_test_state *state = data; + GPR_ASSERT(error == GRPC_ENDPOINT_CB_TIMED_OUT); + gpr_event_set(&state->io_done, (void *)1); +} + +static void write_timeout_test(grpc_endpoint_test_config config, + size_t slice_size) { + gpr_timespec timeout = gpr_time_from_micros(10000); + gpr_timespec write_deadline = gpr_time_add(gpr_now(), timeout); + gpr_timespec test_deadline = + gpr_time_add(gpr_now(), gpr_time_from_micros(2000000)); + struct timeout_test_state state; + int current_data = 1; + gpr_slice *slices; + size_t nblocks; + size_t size; + grpc_endpoint_test_fixture f = begin_test(config, __FUNCTION__, slice_size); + + gpr_event_init(&state.io_done); + + /* TODO(klempner): Factor this out with the equivalent code in tcp_test.c */ + for (size = 1;; size *= 2) { + slices = allocate_blocks(size, 1, &nblocks, ¤t_data); + switch (grpc_endpoint_write(f.client_ep, slices, nblocks, + write_timeout_test_write_handler, &state, + write_deadline)) { + case GRPC_ENDPOINT_WRITE_DONE: + break; + case GRPC_ENDPOINT_WRITE_ERROR: + gpr_log(GPR_ERROR, "error writing"); + abort(); + case GRPC_ENDPOINT_WRITE_PENDING: + GPR_ASSERT(gpr_event_wait(&state.io_done, test_deadline)); + gpr_free(slices); + goto exit; + } + gpr_free(slices); + } +exit: + grpc_endpoint_destroy(f.client_ep); + grpc_endpoint_destroy(f.server_ep); + end_test(config); +} + typedef struct { gpr_event ev; grpc_endpoint *ep; @@ -292,8 +357,9 @@ static void shutdown_during_write_test_read_handler( grpc_endpoint_destroy(st->ep); gpr_event_set(&st->ev, (void *)(gpr_intptr)error); } else { - grpc_endpoint_notify_on_read( - st->ep, shutdown_during_write_test_read_handler, user_data); + grpc_endpoint_notify_on_read(st->ep, + shutdown_during_write_test_read_handler, + user_data, gpr_inf_future); } } @@ -331,13 +397,14 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, gpr_event_init(&read_st.ev); gpr_event_init(&write_st.ev); - grpc_endpoint_notify_on_read( - read_st.ep, shutdown_during_write_test_read_handler, &read_st); + grpc_endpoint_notify_on_read(read_st.ep, + shutdown_during_write_test_read_handler, + &read_st, gpr_inf_future); for (size = 1;; size *= 2) { slices = allocate_blocks(size, 1, &nblocks, ¤t_data); switch (grpc_endpoint_write(write_st.ep, slices, nblocks, shutdown_during_write_test_write_handler, - &write_st)) { + &write_st, gpr_inf_future)) { case GRPC_ENDPOINT_WRITE_DONE: break; case GRPC_ENDPOINT_WRITE_ERROR: @@ -365,5 +432,7 @@ void grpc_endpoint_tests(grpc_endpoint_test_config config) { read_and_write_test(config, 10000000, 100000, 8192, 0); read_and_write_test(config, 1000000, 100000, 1, 0); read_and_write_test(config, 100000000, 100000, 1, 1); + read_timeout_test(config, 1000); + write_timeout_test(config, 1000); shutdown_during_write_test(config, 1000); } diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c index 325c9f0221d..c3a0afdb255 100644 --- a/test/core/iomgr/fd_posix_test.c +++ b/test/core/iomgr/fd_posix_test.c @@ -31,7 +31,8 @@ * */ -#include "src/core/iomgr/fd_posix.h" +/* Test gRPC event manager with a simple TCP upload server and client. */ +#include "src/core/iomgr/iomgr_libevent.h" #include #include @@ -84,7 +85,7 @@ static void create_test_socket(int port, int *socket_fd, } /* Dummy gRPC callback */ -void no_op_cb(void *arg, int success) {} +void no_op_cb(void *arg, enum grpc_em_cb_status status) {} /* =======An upload server to test notify_on_read=========== The server simply reads and counts a stream of bytes. */ @@ -116,10 +117,10 @@ typedef struct { /* Called when an upload session can be safely shutdown. Close session FD and start to shutdown listen FD. */ static void session_shutdown_cb(void *arg, /*session*/ - int success) { + enum grpc_em_cb_status status) { session *se = arg; server *sv = se->sv; - grpc_fd_orphan(se->em_fd, NULL, NULL); + grpc_fd_destroy(se->em_fd, NULL, NULL); gpr_free(se); /* Start to shutdown listen fd. */ grpc_fd_shutdown(sv->em_fd); @@ -127,15 +128,15 @@ static void session_shutdown_cb(void *arg, /*session*/ /* Called when data become readable in a session. */ static void session_read_cb(void *arg, /*session*/ - int success) { + enum grpc_em_cb_status status) { session *se = arg; - int fd = se->em_fd->fd; + int fd = grpc_fd_get(se->em_fd); ssize_t read_once = 0; ssize_t read_total = 0; - if (!success) { - session_shutdown_cb(arg, 1); + if (status == GRPC_CALLBACK_CANCELLED) { + session_shutdown_cb(arg, GRPC_CALLBACK_SUCCESS); return; } @@ -150,7 +151,8 @@ static void session_read_cb(void *arg, /*session*/ It is possible to read nothing due to spurious edge event or data has been drained, In such a case, read() returns -1 and set errno to EAGAIN. */ if (read_once == 0) { - session_shutdown_cb(arg, 1); + grpc_fd_shutdown(se->em_fd); + grpc_fd_notify_on_read(se->em_fd, session_read_cb, se, gpr_inf_future); } else if (read_once == -1) { if (errno == EAGAIN) { /* An edge triggered event is cached in the kernel until next poll. @@ -161,7 +163,8 @@ static void session_read_cb(void *arg, /*session*/ TODO(chenw): in multi-threaded version, callback and polling can be run in different threads. polling may catch a persist read edge event before notify_on_read is called. */ - grpc_fd_notify_on_read(se->em_fd, session_read_cb, se); + GPR_ASSERT(grpc_fd_notify_on_read(se->em_fd, session_read_cb, se, + gpr_inf_future)); } else { gpr_log(GPR_ERROR, "Unhandled read error %s", strerror(errno)); GPR_ASSERT(0); @@ -171,10 +174,11 @@ static void session_read_cb(void *arg, /*session*/ /* Called when the listen FD can be safely shutdown. Close listen FD and signal that server can be shutdown. */ -static void listen_shutdown_cb(void *arg /*server*/, int success) { +static void listen_shutdown_cb(void *arg /*server*/, + enum grpc_em_cb_status status) { server *sv = arg; - grpc_fd_orphan(sv->em_fd, NULL, NULL); + grpc_fd_destroy(sv->em_fd, NULL, NULL); gpr_mu_lock(&sv->mu); sv->done = 1; @@ -184,21 +188,21 @@ static void listen_shutdown_cb(void *arg /*server*/, int success) { /* Called when a new TCP connection request arrives in the listening port. */ static void listen_cb(void *arg, /*=sv_arg*/ - int success) { + enum grpc_em_cb_status status) { server *sv = arg; int fd; int flags; session *se; struct sockaddr_storage ss; socklen_t slen = sizeof(ss); - grpc_fd *listen_em_fd = sv->em_fd; + struct grpc_fd *listen_em_fd = sv->em_fd; - if (!success) { - listen_shutdown_cb(arg, 1); + if (status == GRPC_CALLBACK_CANCELLED) { + listen_shutdown_cb(arg, GRPC_CALLBACK_SUCCESS); return; } - fd = accept(listen_em_fd->fd, (struct sockaddr *)&ss, &slen); + fd = accept(grpc_fd_get(listen_em_fd), (struct sockaddr *)&ss, &slen); GPR_ASSERT(fd >= 0); GPR_ASSERT(fd < FD_SETSIZE); flags = fcntl(fd, F_GETFL, 0); @@ -206,9 +210,11 @@ static void listen_cb(void *arg, /*=sv_arg*/ se = gpr_malloc(sizeof(*se)); se->sv = sv; se->em_fd = grpc_fd_create(fd); - grpc_fd_notify_on_read(se->em_fd, session_read_cb, se); + GPR_ASSERT( + grpc_fd_notify_on_read(se->em_fd, session_read_cb, se, gpr_inf_future)); - grpc_fd_notify_on_read(listen_em_fd, listen_cb, sv); + GPR_ASSERT( + grpc_fd_notify_on_read(listen_em_fd, listen_cb, sv, gpr_inf_future)); } /* Max number of connections pending to be accepted by listen(). */ @@ -233,7 +239,7 @@ static int server_start(server *sv) { sv->em_fd = grpc_fd_create(fd); /* Register to be interested in reading from listen_fd. */ - grpc_fd_notify_on_read(sv->em_fd, listen_cb, sv); + GPR_ASSERT(grpc_fd_notify_on_read(sv->em_fd, listen_cb, sv, gpr_inf_future)); return port; } @@ -279,24 +285,25 @@ static void client_init(client *cl) { } /* Called when a client upload session is ready to shutdown. */ -static void client_session_shutdown_cb(void *arg /*client*/, int success) { +static void client_session_shutdown_cb(void *arg /*client*/, + enum grpc_em_cb_status status) { client *cl = arg; - grpc_fd_orphan(cl->em_fd, NULL, NULL); + grpc_fd_destroy(cl->em_fd, NULL, NULL); + gpr_mu_lock(&cl->mu); cl->done = 1; gpr_cv_signal(&cl->done_cv); + gpr_mu_unlock(&cl->mu); } /* Write as much as possible, then register notify_on_write. */ static void client_session_write(void *arg, /*client*/ - int success) { + enum grpc_em_cb_status status) { client *cl = arg; - int fd = cl->em_fd->fd; + int fd = grpc_fd_get(cl->em_fd); ssize_t write_once = 0; - if (!success) { - gpr_mu_lock(&cl->mu); - client_session_shutdown_cb(arg, 1); - gpr_mu_unlock(&cl->mu); + if (status == GRPC_CALLBACK_CANCELLED) { + client_session_shutdown_cb(arg, GRPC_CALLBACK_SUCCESS); return; } @@ -308,10 +315,14 @@ static void client_session_write(void *arg, /*client*/ if (errno == EAGAIN) { gpr_mu_lock(&cl->mu); if (cl->client_write_cnt < CLIENT_TOTAL_WRITE_CNT) { - grpc_fd_notify_on_write(cl->em_fd, client_session_write, cl); + GPR_ASSERT(grpc_fd_notify_on_write(cl->em_fd, client_session_write, cl, + gpr_inf_future)); cl->client_write_cnt++; } else { - client_session_shutdown_cb(arg, 1); + close(fd); + grpc_fd_shutdown(cl->em_fd); + grpc_fd_notify_on_write(cl->em_fd, client_session_write, cl, + gpr_inf_future); } gpr_mu_unlock(&cl->mu); } else { @@ -333,7 +344,7 @@ static void client_start(client *cl, int port) { cl->em_fd = grpc_fd_create(fd); - client_session_write(cl, 1); + client_session_write(cl, GRPC_CALLBACK_SUCCESS); } /* Wait for the signal to shutdown a client. */ @@ -367,7 +378,7 @@ static void test_grpc_fd() { typedef struct fd_change_data { gpr_mu mu; gpr_cv cv; - void (*cb_that_ran)(void *, int success); + void (*cb_that_ran)(void *, enum grpc_em_cb_status); } fd_change_data; void init_change_data(fd_change_data *fdc) { @@ -381,7 +392,8 @@ void destroy_change_data(fd_change_data *fdc) { gpr_cv_destroy(&fdc->cv); } -static void first_read_callback(void *arg /* fd_change_data */, int success) { +static void first_read_callback(void *arg /* fd_change_data */, + enum grpc_em_cb_status status) { fd_change_data *fdc = arg; gpr_mu_lock(&fdc->mu); @@ -390,7 +402,8 @@ static void first_read_callback(void *arg /* fd_change_data */, int success) { gpr_mu_unlock(&fdc->mu); } -static void second_read_callback(void *arg /* fd_change_data */, int success) { +static void second_read_callback(void *arg /* fd_change_data */, + enum grpc_em_cb_status status) { fd_change_data *fdc = arg; gpr_mu_lock(&fdc->mu); @@ -423,7 +436,7 @@ static void test_grpc_fd_change() { em_fd = grpc_fd_create(sv[0]); /* Register the first callback, then make its FD readable */ - grpc_fd_notify_on_read(em_fd, first_read_callback, &a); + grpc_fd_notify_on_read(em_fd, first_read_callback, &a, gpr_inf_future); data = 0; result = write(sv[1], &data, 1); GPR_ASSERT(result == 1); @@ -442,7 +455,7 @@ static void test_grpc_fd_change() { /* Now register a second callback with distinct change data, and do the same thing again. */ - grpc_fd_notify_on_read(em_fd, second_read_callback, &b); + grpc_fd_notify_on_read(em_fd, second_read_callback, &b, gpr_inf_future); data = 0; result = write(sv[1], &data, 1); GPR_ASSERT(result == 1); @@ -455,9 +468,48 @@ static void test_grpc_fd_change() { GPR_ASSERT(b.cb_that_ran == second_read_callback); gpr_mu_unlock(&b.mu); - grpc_fd_orphan(em_fd, NULL, NULL); + grpc_fd_destroy(em_fd, NULL, NULL); destroy_change_data(&a); destroy_change_data(&b); + close(sv[0]); + close(sv[1]); +} + +void timeout_callback(void *arg, enum grpc_em_cb_status status) { + if (status == GRPC_CALLBACK_TIMED_OUT) { + gpr_event_set(arg, (void *)1); + } else { + gpr_event_set(arg, (void *)2); + } +} + +void test_grpc_fd_notify_timeout() { + grpc_fd *em_fd; + gpr_event ev; + int flags; + int sv[2]; + gpr_timespec timeout; + gpr_timespec deadline; + + gpr_event_init(&ev); + + GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); + flags = fcntl(sv[0], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); + flags = fcntl(sv[1], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); + + em_fd = grpc_fd_create(sv[0]); + + timeout = gpr_time_from_micros(1000000); + deadline = gpr_time_add(gpr_now(), timeout); + + grpc_fd_notify_on_read(em_fd, timeout_callback, &ev, deadline); + + GPR_ASSERT(gpr_event_wait(&ev, gpr_time_add(deadline, timeout))); + + GPR_ASSERT(gpr_event_get(&ev) == (void *)1); + grpc_fd_destroy(em_fd, NULL, NULL); close(sv[1]); } @@ -466,6 +518,7 @@ int main(int argc, char **argv) { grpc_iomgr_init(); test_grpc_fd(); test_grpc_fd_change(); + test_grpc_fd_notify_timeout(); grpc_iomgr_shutdown(); return 0; } diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c index 2d0a89a1f52..cb1cd0bc165 100644 --- a/test/core/iomgr/tcp_client_posix_test.c +++ b/test/core/iomgr/tcp_client_posix_test.c @@ -44,7 +44,7 @@ #include static gpr_timespec test_deadline() { - return gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); + return gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)); } static void must_succeed(void *arg, grpc_endpoint *tcp) { diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 7fd2567cec5..6a4ef0f9842 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -154,7 +154,7 @@ static void read_cb(void *user_data, gpr_slice *slices, size_t nslices, if (state->read_bytes >= state->target_read_bytes) { gpr_cv_signal(&state->cv); } else { - grpc_endpoint_notify_on_read(state->ep, read_cb, state); + grpc_endpoint_notify_on_read(state->ep, read_cb, state, gpr_inf_future); } gpr_mu_unlock(&state->mu); } @@ -183,7 +183,7 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { state.read_bytes = 0; state.target_read_bytes = written_bytes; - grpc_endpoint_notify_on_read(ep, read_cb, &state); + grpc_endpoint_notify_on_read(ep, read_cb, &state, gpr_inf_future); gpr_mu_lock(&state.mu); for (;;) { @@ -225,7 +225,7 @@ static void large_read_test(ssize_t slice_size) { state.read_bytes = 0; state.target_read_bytes = written_bytes; - grpc_endpoint_notify_on_read(ep, read_cb, &state); + grpc_endpoint_notify_on_read(ep, read_cb, &state, gpr_inf_future); gpr_mu_lock(&state.mu); for (;;) { @@ -363,8 +363,8 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - if (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state) == - GRPC_ENDPOINT_WRITE_DONE) { + if (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state, + gpr_inf_future) == GRPC_ENDPOINT_WRITE_DONE) { /* Write completed immediately */ read_bytes = drain_socket(sv[0]); GPR_ASSERT(read_bytes == num_bytes); @@ -421,13 +421,15 @@ static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - switch (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state)) { + switch (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state, + gpr_inf_future)) { case GRPC_ENDPOINT_WRITE_DONE: case GRPC_ENDPOINT_WRITE_ERROR: /* Write completed immediately */ break; case GRPC_ENDPOINT_WRITE_PENDING: - grpc_endpoint_notify_on_read(ep, read_done_for_write_error, NULL); + grpc_endpoint_notify_on_read(ep, read_done_for_write_error, NULL, + gpr_inf_future); gpr_mu_lock(&state.mu); for (;;) { if (state.write_done) { diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c index f30ff917cb5..cb77a880620 100644 --- a/test/core/iomgr/tcp_server_posix_test.c +++ b/test/core/iomgr/tcp_server_posix_test.c @@ -66,7 +66,7 @@ static void test_no_op() { static void test_no_op_with_start() { grpc_tcp_server *s = grpc_tcp_server_create(); LOG_TEST(); - grpc_tcp_server_start(s, NULL, on_connect, NULL); + grpc_tcp_server_start(s, on_connect, NULL); grpc_tcp_server_destroy(s); } @@ -93,7 +93,7 @@ static void test_no_op_with_port_and_start() { GPR_ASSERT( grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr))); - grpc_tcp_server_start(s, NULL, on_connect, NULL); + grpc_tcp_server_start(s, on_connect, NULL); grpc_tcp_server_destroy(s); } @@ -120,7 +120,7 @@ static void test_connect(int n) { GPR_ASSERT(getsockname(svrfd, (struct sockaddr *)&addr, &addr_len) == 0); GPR_ASSERT(addr_len <= sizeof(addr)); - grpc_tcp_server_start(s, NULL, on_connect, NULL); + grpc_tcp_server_start(s, on_connect, NULL); for (i = 0; i < n; i++) { deadline = gpr_time_add(gpr_now(), gpr_time_from_micros(10000000)); diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index d4baa64725f..9311d6ba119 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -153,7 +153,8 @@ static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { int verified = 0; gpr_log(GPR_INFO, "Start test left over"); - grpc_endpoint_notify_on_read(f.client_ep, verify_leftover, &verified); + grpc_endpoint_notify_on_read(f.client_ep, verify_leftover, &verified, + gpr_inf_future); GPR_ASSERT(verified == 1); grpc_endpoint_shutdown(f.client_ep); @@ -186,7 +187,7 @@ static void test_destroy_ep_early(grpc_endpoint_test_config config, grpc_endpoint_test_fixture f = config.create_fixture(slice_size); gpr_log(GPR_INFO, "Start test destroy early"); - grpc_endpoint_notify_on_read(f.client_ep, destroy_early, &f); + grpc_endpoint_notify_on_read(f.client_ep, destroy_early, &f, gpr_inf_future); grpc_endpoint_shutdown(f.server_ep); grpc_endpoint_destroy(f.server_ep); diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index 6cc5a8b2932..ffce5f6ecd5 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -115,12 +115,10 @@ - + - - + - @@ -145,9 +143,9 @@ - + @@ -160,8 +158,8 @@ - + @@ -238,15 +236,11 @@ - - - + - + - - - + @@ -338,10 +332,10 @@ - - + + diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj index 6cc5a8b2932..ffce5f6ecd5 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj @@ -115,12 +115,10 @@ - + - - + - @@ -145,9 +143,9 @@ - + @@ -160,8 +158,8 @@ - + @@ -238,15 +236,11 @@ - - - + - + - - - + @@ -338,10 +332,10 @@ - - + + From 58393c20bc29cf4f9e6fe15516125661e1957db7 Mon Sep 17 00:00:00 2001 From: ctiller Date: Wed, 7 Jan 2015 14:03:30 -0800 Subject: [PATCH 02/29] Remove libevent. Fixed any exposed bugs across the stack. Add a poll() based implementation. Heavily leverages pollset infrastructure to allow small polls to be the norm. Exposes a mechanism to plug in epoll/kqueue for platforms where we have them. Simplify iomgr callbacks to return one bit of success or failure (instead of the multi valued result that was mostly unused previously). This will ease the burden on new implementations, and the previous system provided no real value anyway. Removed timeouts on endpoint read/write routines. This simplifies porting burden by providing a more orthogonal interface, and the functionality can always be replicated when desired by using an alarm combined with endpoint_shutdown. I'm fairly certain we ended up with this interface because it was convenient to do from libevent. Things that need attention still: - adding an fd to a pollset is O(n^2) - but this is probably ok given that we'll not use this for multipolling once platform specific implementations are added. - we rely on the backup poller too often - especially for SSL handshakes and for client connection establishment we should have a better mechanism ([] [] - Linux needs to use epoll for multiple fds, FreeBSD variants (including Darwin) need to use kqueue. ([] [] - Linux needs to use eventfd for poll kicking. ([] Change on 2015/01/07 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83461069 --- Makefile | 20 +- build.json | 20 +- include/grpc/support/port_platform.h | 3 + include/grpc/support/time.h | 2 + src/core/channel/child_channel.c | 36 +- src/core/channel/child_channel.h | 3 +- src/core/channel/client_channel.c | 20 +- src/core/channel/client_setup.c | 5 +- src/core/httpcli/httpcli.c | 10 +- src/core/iomgr/alarm.c | 34 +- src/core/iomgr/alarm_internal.h | 5 +- src/core/iomgr/endpoint.c | 14 +- src/core/iomgr/endpoint.h | 17 +- src/core/iomgr/fd_posix.c | 274 ++++++++ src/core/iomgr/fd_posix.h | 138 ++++ src/core/iomgr/iomgr.c | 204 ++++++ src/core/iomgr/iomgr.h | 11 +- ...ibevent_use_threads.c => iomgr_internal.h} | 35 +- src/core/iomgr/iomgr_libevent.c | 652 ------------------ src/core/iomgr/iomgr_libevent.h | 206 ------ src/core/iomgr/{pollset.c => iomgr_posix.c} | 7 +- ...letion_queue_interface.h => iomgr_posix.h} | 15 +- src/core/iomgr/pollset.h | 21 +- .../pollset_multipoller_with_poll_posix.c | 237 +++++++ src/core/iomgr/pollset_posix.c | 340 +++++++++ src/core/iomgr/pollset_posix.h | 95 +++ src/core/iomgr/resolve_address_posix.c | 6 +- src/core/iomgr/tcp_client_posix.c | 76 +- src/core/iomgr/tcp_posix.c | 67 +- src/core/iomgr/tcp_posix.h | 2 +- src/core/iomgr/tcp_server.h | 4 +- src/core/iomgr/tcp_server_posix.c | 38 +- src/core/security/credentials.c | 5 +- src/core/security/secure_endpoint.c | 15 +- src/core/security/secure_transport_setup.c | 12 +- src/core/security/server_secure_chttp2.c | 4 +- src/core/support/time.c | 15 + src/core/surface/call.c | 4 +- src/core/surface/completion_queue.c | 66 +- src/core/surface/server.c | 13 +- src/core/surface/server.h | 3 +- src/core/surface/server_chttp2.c | 4 +- src/core/transport/chttp2_transport.c | 5 +- test/core/end2end/cq_verifier.c | 7 +- .../end2end/fixtures/chttp2_socket_pair.c | 1 + .../chttp2_socket_pair_one_byte_at_a_time.c | 1 + .../core/end2end/tests/invoke_large_request.c | 2 +- .../end2end/tests/max_concurrent_streams.c | 56 +- test/core/iomgr/alarm_list_test.c | 50 +- test/core/iomgr/alarm_test.c | 26 +- test/core/iomgr/endpoint_tests.c | 113 +-- test/core/iomgr/fd_posix_test.c | 127 +--- test/core/iomgr/tcp_client_posix_test.c | 2 +- test/core/iomgr/tcp_posix_test.c | 16 +- test/core/iomgr/tcp_server_posix_test.c | 6 +- test/core/security/secure_endpoint_test.c | 5 +- vsprojects/vs2013/grpc.vcxproj | 24 +- vsprojects/vs2013/grpc_unsecure.vcxproj | 24 +- 58 files changed, 1806 insertions(+), 1417 deletions(-) create mode 100644 src/core/iomgr/fd_posix.c create mode 100644 src/core/iomgr/fd_posix.h create mode 100644 src/core/iomgr/iomgr.c rename src/core/iomgr/{iomgr_libevent_use_threads.c => iomgr_internal.h} (67%) delete mode 100644 src/core/iomgr/iomgr_libevent.c delete mode 100644 src/core/iomgr/iomgr_libevent.h rename src/core/iomgr/{pollset.c => iomgr_posix.c} (89%) rename src/core/iomgr/{iomgr_completion_queue_interface.h => iomgr_posix.h} (79%) create mode 100644 src/core/iomgr/pollset_multipoller_with_poll_posix.c create mode 100644 src/core/iomgr/pollset_posix.c create mode 100644 src/core/iomgr/pollset_posix.h diff --git a/Makefile b/Makefile index 49b0bd629de..a48e621debd 100644 --- a/Makefile +++ b/Makefile @@ -1229,9 +1229,11 @@ LIBGRPC_SRC = \ src/core/iomgr/alarm_heap.c \ src/core/iomgr/endpoint.c \ src/core/iomgr/endpoint_pair_posix.c \ - src/core/iomgr/iomgr_libevent.c \ - src/core/iomgr/iomgr_libevent_use_threads.c \ - src/core/iomgr/pollset.c \ + src/core/iomgr/fd_posix.c \ + src/core/iomgr/iomgr.c \ + src/core/iomgr/iomgr_posix.c \ + src/core/iomgr/pollset_multipoller_with_poll_posix.c \ + src/core/iomgr/pollset_posix.c \ src/core/iomgr/resolve_address_posix.c \ src/core/iomgr/sockaddr_utils.c \ src/core/iomgr/socket_utils_common_posix.c \ @@ -1277,8 +1279,8 @@ LIBGRPC_SRC = \ src/core/transport/chttp2/stream_encoder.c \ src/core/transport/chttp2/stream_map.c \ src/core/transport/chttp2/timeout_encoding.c \ - src/core/transport/chttp2_transport.c \ src/core/transport/chttp2/varint.c \ + src/core/transport/chttp2_transport.c \ src/core/transport/metadata.c \ src/core/transport/stream_op.c \ src/core/transport/transport.c \ @@ -1379,9 +1381,11 @@ LIBGRPC_UNSECURE_SRC = \ src/core/iomgr/alarm_heap.c \ src/core/iomgr/endpoint.c \ src/core/iomgr/endpoint_pair_posix.c \ - src/core/iomgr/iomgr_libevent.c \ - src/core/iomgr/iomgr_libevent_use_threads.c \ - src/core/iomgr/pollset.c \ + src/core/iomgr/fd_posix.c \ + src/core/iomgr/iomgr.c \ + src/core/iomgr/iomgr_posix.c \ + src/core/iomgr/pollset_multipoller_with_poll_posix.c \ + src/core/iomgr/pollset_posix.c \ src/core/iomgr/resolve_address_posix.c \ src/core/iomgr/sockaddr_utils.c \ src/core/iomgr/socket_utils_common_posix.c \ @@ -1427,8 +1431,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/transport/chttp2/stream_encoder.c \ src/core/transport/chttp2/stream_map.c \ src/core/transport/chttp2/timeout_encoding.c \ - src/core/transport/chttp2_transport.c \ src/core/transport/chttp2/varint.c \ + src/core/transport/chttp2_transport.c \ src/core/transport/metadata.c \ src/core/transport/stream_op.c \ src/core/transport/transport.c \ diff --git a/build.json b/build.json index e0bf2806359..e0e05c8eaf4 100644 --- a/build.json +++ b/build.json @@ -35,9 +35,11 @@ "src/core/iomgr/alarm_heap.c", "src/core/iomgr/endpoint.c", "src/core/iomgr/endpoint_pair_posix.c", - "src/core/iomgr/iomgr_libevent.c", - "src/core/iomgr/iomgr_libevent_use_threads.c", - "src/core/iomgr/pollset.c", + "src/core/iomgr/fd_posix.c", + "src/core/iomgr/iomgr.c", + "src/core/iomgr/iomgr_posix.c", + "src/core/iomgr/pollset_multipoller_with_poll_posix.c", + "src/core/iomgr/pollset_posix.c", "src/core/iomgr/resolve_address_posix.c", "src/core/iomgr/sockaddr_utils.c", "src/core/iomgr/socket_utils_common_posix.c", @@ -83,8 +85,8 @@ "src/core/transport/chttp2/stream_encoder.c", "src/core/transport/chttp2/stream_map.c", "src/core/transport/chttp2/timeout_encoding.c", - "src/core/transport/chttp2_transport.c", "src/core/transport/chttp2/varint.c", + "src/core/transport/chttp2_transport.c", "src/core/transport/metadata.c", "src/core/transport/stream_op.c", "src/core/transport/transport.c", @@ -120,10 +122,12 @@ "src/core/iomgr/alarm_internal.h", "src/core/iomgr/endpoint.h", "src/core/iomgr/endpoint_pair.h", - "src/core/iomgr/iomgr_completion_queue_interface.h", + "src/core/iomgr/fd_posix.h", "src/core/iomgr/iomgr.h", - "src/core/iomgr/iomgr_libevent.h", + "src/core/iomgr/iomgr_internal.h", + "src/core/iomgr/iomgr_posix.h", "src/core/iomgr/pollset.h", + "src/core/iomgr/pollset_posix.h", "src/core/iomgr/resolve_address.h", "src/core/iomgr/sockaddr.h", "src/core/iomgr/sockaddr_posix.h", @@ -148,9 +152,9 @@ "src/core/surface/server.h", "src/core/surface/surface_trace.h", "src/core/transport/chttp2/bin_encoder.h", + "src/core/transport/chttp2/frame.h", "src/core/transport/chttp2/frame_data.h", "src/core/transport/chttp2/frame_goaway.h", - "src/core/transport/chttp2/frame.h", "src/core/transport/chttp2/frame_ping.h", "src/core/transport/chttp2/frame_rst_stream.h", "src/core/transport/chttp2/frame_settings.h", @@ -163,8 +167,8 @@ "src/core/transport/chttp2/stream_encoder.h", "src/core/transport/chttp2/stream_map.h", "src/core/transport/chttp2/timeout_encoding.h", - "src/core/transport/chttp2_transport.h", "src/core/transport/chttp2/varint.h", + "src/core/transport/chttp2_transport.h", "src/core/transport/metadata.h", "src/core/transport/stream_op.h", "src/core/transport/transport.h", diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h index 9e5c9ff2ace..27a7b5529f7 100644 --- a/include/grpc/support/port_platform.h +++ b/include/grpc/support/port_platform.h @@ -54,6 +54,7 @@ #define GPR_CPU_LINUX 1 #define GPR_GCC_SYNC 1 #define GPR_LIBEVENT 1 +#define GPR_POSIX_MULTIPOLL_WITH_POLL 1 #define GPR_POSIX_SOCKET 1 #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 @@ -65,6 +66,7 @@ #define GPR_GCC_ATOMIC 1 #define GPR_LIBEVENT 1 #define GPR_LINUX 1 +#define GPR_POSIX_MULTIPOLL_WITH_POLL 1 #define GPR_POSIX_SOCKET 1 #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_STRING 1 @@ -80,6 +82,7 @@ #define GPR_GCC_ATOMIC 1 #define GPR_LIBEVENT 1 #define GPR_POSIX_LOG 1 +#define GPR_POSIX_MULTIPOLL_WITH_POLL 1 #define GPR_POSIX_SOCKET 1 #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h index 5a57d947681..41d1e88dc94 100644 --- a/include/grpc/support/time.h +++ b/include/grpc/support/time.h @@ -94,6 +94,8 @@ gpr_timespec gpr_time_from_seconds(long x); gpr_timespec gpr_time_from_minutes(long x); gpr_timespec gpr_time_from_hours(long x); +gpr_int32 gpr_time_to_millis(gpr_timespec timespec); + /* Return 1 if two times are equal or within threshold of each other, 0 otherwise */ int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold); diff --git a/src/core/channel/child_channel.c b/src/core/channel/child_channel.c index e67b8236974..3778f4fb88f 100644 --- a/src/core/channel/child_channel.c +++ b/src/core/channel/child_channel.c @@ -85,19 +85,19 @@ static void lb_channel_op(grpc_channel_element *elem, grpc_channel_op *op) { lb_channel_data *chand = elem->channel_data; grpc_channel_element *back; + int calling_back = 0; switch (op->dir) { case GRPC_CALL_UP: gpr_mu_lock(&chand->mu); back = chand->back; - if (back) chand->calling_back++; + if (back) { + chand->calling_back++; + calling_back = 1; + } gpr_mu_unlock(&chand->mu); if (back) { back->filter->channel_op(chand->back, elem, op); - gpr_mu_lock(&chand->mu); - chand->calling_back--; - gpr_cv_broadcast(&chand->cv); - gpr_mu_unlock(&chand->mu); } else if (op->type == GRPC_TRANSPORT_GOAWAY) { gpr_slice_unref(op->data.goaway.message); } @@ -107,23 +107,27 @@ static void lb_channel_op(grpc_channel_element *elem, break; } + gpr_mu_lock(&chand->mu); switch (op->type) { case GRPC_TRANSPORT_CLOSED: - gpr_mu_lock(&chand->mu); chand->disconnected = 1; maybe_destroy_channel(grpc_channel_stack_from_top_element(elem)); - gpr_mu_unlock(&chand->mu); break; case GRPC_CHANNEL_GOAWAY: - gpr_mu_lock(&chand->mu); chand->sent_goaway = 1; - gpr_mu_unlock(&chand->mu); break; case GRPC_CHANNEL_DISCONNECT: case GRPC_TRANSPORT_GOAWAY: case GRPC_ACCEPT_CALL: break; } + + if (calling_back) { + chand->calling_back--; + gpr_cv_signal(&chand->cv); + maybe_destroy_channel(grpc_channel_stack_from_top_element(elem)); + } + gpr_mu_unlock(&chand->mu); } /* Constructor for call_data */ @@ -177,7 +181,9 @@ const grpc_channel_filter grpc_child_channel_top_filter = { #define LINK_BACK_ELEM_FROM_CALL(call) grpc_call_stack_element((call), 0) -static void finally_destroy_channel(void *c, grpc_iomgr_cb_status status) { +static void finally_destroy_channel(void *c, int success) { + /* ignore success or not... this is a destruction callback and will only + happen once - the only purpose here is to release resources */ grpc_child_channel *channel = c; lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data; /* wait for the initiator to leave the mutex */ @@ -187,7 +193,7 @@ static void finally_destroy_channel(void *c, grpc_iomgr_cb_status status) { gpr_free(channel); } -static void send_farewells(void *c, grpc_iomgr_cb_status status) { +static void send_farewells(void *c, int success) { grpc_child_channel *channel = c; grpc_channel_element *lbelem = LINK_BACK_ELEM_FROM_CHANNEL(channel); lb_channel_data *chand = lbelem->channel_data; @@ -221,7 +227,7 @@ static void send_farewells(void *c, grpc_iomgr_cb_status status) { static void maybe_destroy_channel(grpc_child_channel *channel) { lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data; if (chand->destroyed && chand->disconnected && chand->active_calls == 0 && - !chand->sending_farewell) { + !chand->sending_farewell && !chand->calling_back) { grpc_iomgr_add_callback(finally_destroy_channel, channel); } else if (chand->destroyed && !chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && @@ -249,14 +255,16 @@ grpc_child_channel *grpc_child_channel_create( return stk; } -void grpc_child_channel_destroy(grpc_child_channel *channel) { +void grpc_child_channel_destroy(grpc_child_channel *channel, + int wait_for_callbacks) { grpc_channel_element *lbelem = LINK_BACK_ELEM_FROM_CHANNEL(channel); lb_channel_data *chand = lbelem->channel_data; gpr_mu_lock(&chand->mu); - while (chand->calling_back) { + while (wait_for_callbacks && chand->calling_back) { gpr_cv_wait(&chand->cv, &chand->mu, gpr_inf_future); } + chand->back = NULL; chand->destroyed = 1; maybe_destroy_channel(channel); diff --git a/src/core/channel/child_channel.h b/src/core/channel/child_channel.h index 9fb2a17e29d..3ba4c1b8a9e 100644 --- a/src/core/channel/child_channel.h +++ b/src/core/channel/child_channel.h @@ -53,7 +53,8 @@ void grpc_child_channel_handle_op(grpc_child_channel *channel, grpc_channel_op *op); grpc_channel_element *grpc_child_channel_get_bottom_element( grpc_child_channel *channel); -void grpc_child_channel_destroy(grpc_child_channel *channel); +void grpc_child_channel_destroy(grpc_child_channel *channel, + int wait_for_callbacks); grpc_child_call *grpc_child_channel_create_call(grpc_child_channel *channel, grpc_call_element *parent); diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c index fd883a08cab..46283835a05 100644 --- a/src/core/channel/client_channel.c +++ b/src/core/channel/client_channel.c @@ -294,14 +294,6 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, } } -static void finally_destroy_channel(void *arg, grpc_iomgr_cb_status status) { - grpc_child_channel_destroy(arg); -} - -static void destroy_channel_later(grpc_child_channel *channel) { - grpc_iomgr_add_callback(finally_destroy_channel, channel); -} - static void channel_op(grpc_channel_element *elem, grpc_channel_element *from_elem, grpc_channel_op *op) { channel_data *chand = elem->channel_data; @@ -317,7 +309,7 @@ static void channel_op(grpc_channel_element *elem, gpr_mu_unlock(&chand->mu); if (child_channel) { grpc_child_channel_handle_op(child_channel, op); - destroy_channel_later(child_channel); + grpc_child_channel_destroy(child_channel, 1); } else { gpr_slice_unref(op->data.goaway.message); } @@ -329,7 +321,7 @@ static void channel_op(grpc_channel_element *elem, chand->active_child = NULL; gpr_mu_unlock(&chand->mu); if (child_channel) { - destroy_channel_later(child_channel); + grpc_child_channel_destroy(child_channel, 1); } break; case GRPC_TRANSPORT_GOAWAY: @@ -344,7 +336,7 @@ static void channel_op(grpc_channel_element *elem, } gpr_mu_unlock(&chand->mu); if (child_channel) { - destroy_channel_later(child_channel); + grpc_child_channel_destroy(child_channel, 0); } gpr_slice_unref(op->data.goaway.message); break; @@ -360,7 +352,7 @@ static void channel_op(grpc_channel_element *elem, } gpr_mu_unlock(&chand->mu); if (child_channel) { - destroy_channel_later(child_channel); + grpc_child_channel_destroy(child_channel, 0); } break; default: @@ -445,7 +437,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) { grpc_transport_setup_cancel(chand->transport_setup); if (chand->active_child) { - grpc_child_channel_destroy(chand->active_child); + grpc_child_channel_destroy(chand->active_child, 1); chand->active_child = NULL; } @@ -549,7 +541,7 @@ grpc_transport_setup_result grpc_client_channel_transport_setup_complete( gpr_free(child_filters); if (old_active) { - grpc_child_channel_destroy(old_active); + grpc_child_channel_destroy(old_active, 1); } return result; diff --git a/src/core/channel/client_setup.c b/src/core/channel/client_setup.c index b1194e278de..ebaf816902b 100644 --- a/src/core/channel/client_setup.c +++ b/src/core/channel/client_setup.c @@ -166,8 +166,7 @@ int grpc_client_setup_request_should_continue(grpc_client_setup_request *r) { return result; } -static void backoff_alarm_done(void *arg /* grpc_client_setup */, - grpc_iomgr_cb_status status) { +static void backoff_alarm_done(void *arg /* grpc_client_setup */, int success) { grpc_client_setup *s = arg; grpc_client_setup_request *r = gpr_malloc(sizeof(grpc_client_setup_request)); r->setup = s; @@ -177,7 +176,7 @@ static void backoff_alarm_done(void *arg /* grpc_client_setup */, gpr_mu_lock(&s->mu); s->active_request = r; s->in_alarm = 0; - if (status != GRPC_CALLBACK_SUCCESS) { + if (!success) { if (0 == --s->refs) { gpr_mu_unlock(&s->mu); destroy_setup(s); diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index 06d73e40f52..2143eeb63d0 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -101,12 +101,11 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, switch (status) { case GRPC_ENDPOINT_CB_OK: - grpc_endpoint_notify_on_read(req->ep, on_read, req, gpr_inf_future); + grpc_endpoint_notify_on_read(req->ep, on_read, req); break; case GRPC_ENDPOINT_CB_EOF: case GRPC_ENDPOINT_CB_ERROR: case GRPC_ENDPOINT_CB_SHUTDOWN: - case GRPC_ENDPOINT_CB_TIMED_OUT: if (!req->have_read_byte) { next_address(req); } else { @@ -123,7 +122,7 @@ done: static void on_written(internal_request *req) { gpr_log(GPR_DEBUG, "%s", __FUNCTION__); - grpc_endpoint_notify_on_read(req->ep, on_read, req, gpr_inf_future); + grpc_endpoint_notify_on_read(req->ep, on_read, req); } static void done_write(void *arg, grpc_endpoint_cb_status status) { @@ -136,7 +135,6 @@ static void done_write(void *arg, grpc_endpoint_cb_status status) { case GRPC_ENDPOINT_CB_EOF: case GRPC_ENDPOINT_CB_SHUTDOWN: case GRPC_ENDPOINT_CB_ERROR: - case GRPC_ENDPOINT_CB_TIMED_OUT: next_address(req); break; } @@ -145,8 +143,8 @@ static void done_write(void *arg, grpc_endpoint_cb_status status) { static void start_write(internal_request *req) { gpr_slice_ref(req->request_text); gpr_log(GPR_DEBUG, "%s", __FUNCTION__); - switch (grpc_endpoint_write(req->ep, &req->request_text, 1, done_write, req, - gpr_inf_future)) { + switch ( + grpc_endpoint_write(req->ep, &req->request_text, 1, done_write, req)) { case GRPC_ENDPOINT_WRITE_DONE: on_written(req); break; diff --git a/src/core/iomgr/alarm.c b/src/core/iomgr/alarm.c index b7238f716a9..26648793238 100644 --- a/src/core/iomgr/alarm.c +++ b/src/core/iomgr/alarm.c @@ -71,8 +71,8 @@ static shard_type g_shards[NUM_SHARDS]; /* Protected by g_mu */ static shard_type *g_shard_queue[NUM_SHARDS]; -static int run_some_expired_alarms(gpr_timespec now, - grpc_iomgr_cb_status status); +static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now, + gpr_timespec *next, int success); static gpr_timespec compute_min_deadline(shard_type *shard) { return grpc_alarm_heap_is_empty(&shard->heap) @@ -102,7 +102,7 @@ void grpc_alarm_list_init(gpr_timespec now) { void grpc_alarm_list_shutdown() { int i; - while (run_some_expired_alarms(gpr_inf_future, GRPC_CALLBACK_CANCELLED)) + while (run_some_expired_alarms(NULL, gpr_inf_future, NULL, 0)) ; for (i = 0; i < NUM_SHARDS; i++) { shard_type *shard = &g_shards[i]; @@ -233,7 +233,7 @@ void grpc_alarm_cancel(grpc_alarm *alarm) { gpr_mu_unlock(&shard->mu); if (triggered) { - alarm->cb(alarm->cb_arg, GRPC_CALLBACK_CANCELLED); + alarm->cb(alarm->cb_arg, 0); } } @@ -299,8 +299,8 @@ static size_t pop_alarms(shard_type *shard, gpr_timespec now, return n; } -static int run_some_expired_alarms(gpr_timespec now, - grpc_iomgr_cb_status status) { +static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now, + gpr_timespec *next, int success) { size_t n = 0; size_t i; grpc_alarm *alarms[MAX_ALARMS_PER_CHECK]; @@ -329,19 +329,35 @@ static int run_some_expired_alarms(gpr_timespec now, note_deadline_change(g_shard_queue[0]); } + if (next) { + *next = gpr_time_min(*next, g_shard_queue[0]->min_deadline); + } + gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_checker_mu); + } else if (next) { + gpr_mu_lock(&g_mu); + *next = gpr_time_min(*next, g_shard_queue[0]->min_deadline); + gpr_mu_unlock(&g_mu); + } + + if (n && drop_mu) { + gpr_mu_unlock(drop_mu); } for (i = 0; i < n; i++) { - alarms[i]->cb(alarms[i]->cb_arg, status); + alarms[i]->cb(alarms[i]->cb_arg, success); + } + + if (n && drop_mu) { + gpr_mu_lock(drop_mu); } return n; } -int grpc_alarm_check(gpr_timespec now) { - return run_some_expired_alarms(now, GRPC_CALLBACK_SUCCESS); +int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next) { + return run_some_expired_alarms(drop_mu, now, next, 1); } gpr_timespec grpc_alarm_list_next_timeout() { diff --git a/src/core/iomgr/alarm_internal.h b/src/core/iomgr/alarm_internal.h index e605ff84f9e..12b6ab4286d 100644 --- a/src/core/iomgr/alarm_internal.h +++ b/src/core/iomgr/alarm_internal.h @@ -34,9 +34,12 @@ #ifndef __GRPC_INTERNAL_IOMGR_ALARM_INTERNAL_H_ #define __GRPC_INTERNAL_IOMGR_ALARM_INTERNAL_H_ +#include +#include + /* iomgr internal api for dealing with alarms */ -int grpc_alarm_check(gpr_timespec now); +int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next); void grpc_alarm_list_init(gpr_timespec now); void grpc_alarm_list_shutdown(); diff --git a/src/core/iomgr/endpoint.c b/src/core/iomgr/endpoint.c index f1944bf672c..9e5d56389d2 100644 --- a/src/core/iomgr/endpoint.c +++ b/src/core/iomgr/endpoint.c @@ -34,14 +34,16 @@ #include "src/core/iomgr/endpoint.h" void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data, gpr_timespec deadline) { - ep->vtable->notify_on_read(ep, cb, user_data, deadline); + void *user_data) { + ep->vtable->notify_on_read(ep, cb, user_data); } -grpc_endpoint_write_status grpc_endpoint_write( - grpc_endpoint *ep, gpr_slice *slices, size_t nslices, - grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline) { - return ep->vtable->write(ep, slices, nslices, cb, user_data, deadline); +grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data) { + return ep->vtable->write(ep, slices, nslices, cb, user_data); } void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h index bbd800bea85..ec86d9a1460 100644 --- a/src/core/iomgr/endpoint.h +++ b/src/core/iomgr/endpoint.h @@ -48,8 +48,7 @@ typedef enum grpc_endpoint_cb_status { GRPC_ENDPOINT_CB_OK = 0, /* Call completed successfully */ GRPC_ENDPOINT_CB_EOF, /* Call completed successfully, end of file reached */ GRPC_ENDPOINT_CB_SHUTDOWN, /* Call interrupted by shutdown */ - GRPC_ENDPOINT_CB_ERROR, /* Call interrupted by socket error */ - GRPC_ENDPOINT_CB_TIMED_OUT /* Call timed out */ + GRPC_ENDPOINT_CB_ERROR /* Call interrupted by socket error */ } grpc_endpoint_cb_status; typedef enum grpc_endpoint_write_status { @@ -66,10 +65,10 @@ typedef void (*grpc_endpoint_write_cb)(void *user_data, struct grpc_endpoint_vtable { void (*notify_on_read)(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data, gpr_timespec deadline); + void *user_data); grpc_endpoint_write_status (*write)(grpc_endpoint *ep, gpr_slice *slices, size_t nslices, grpc_endpoint_write_cb cb, - void *user_data, gpr_timespec deadline); + void *user_data); void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset); void (*shutdown)(grpc_endpoint *ep); void (*destroy)(grpc_endpoint *ep); @@ -77,7 +76,7 @@ struct grpc_endpoint_vtable { /* When data is available on the connection, calls the callback with slices. */ void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data, gpr_timespec deadline); + void *user_data); /* Write slices out to the socket. @@ -85,9 +84,11 @@ void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, returns GRPC_ENDPOINT_WRITE_DONE. Otherwise it returns GRPC_ENDPOINT_WRITE_PENDING and calls cb when the connection is ready for more data. */ -grpc_endpoint_write_status grpc_endpoint_write( - grpc_endpoint *ep, gpr_slice *slices, size_t nslices, - grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline); +grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data); /* Causes any pending read/write callbacks to run immediately with GRPC_ENDPOINT_CB_SHUTDOWN status */ diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c new file mode 100644 index 00000000000..3cd2f9a8e0c --- /dev/null +++ b/src/core/iomgr/fd_posix.c @@ -0,0 +1,274 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/iomgr/fd_posix.h" + +#include +#include + +#include "src/core/iomgr/iomgr_internal.h" +#include +#include +#include + +enum descriptor_state { NOT_READY, READY, WAITING }; + +static void destroy(grpc_fd *fd) { + grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data); + gpr_mu_destroy(&fd->set_state_mu); + gpr_free(fd->watchers); + gpr_free(fd); + grpc_iomgr_unref(); +} + +static void ref_by(grpc_fd *fd, int n) { + gpr_atm_no_barrier_fetch_add(&fd->refst, n); +} + +static void unref_by(grpc_fd *fd, int n) { + if (gpr_atm_full_fetch_add(&fd->refst, -n) == n) { + destroy(fd); + } +} + +static void do_nothing(void *ignored, int success) {} + +grpc_fd *grpc_fd_create(int fd) { + grpc_fd *r = gpr_malloc(sizeof(grpc_fd)); + grpc_iomgr_ref(); + gpr_atm_rel_store(&r->refst, 1); + gpr_atm_rel_store(&r->readst.state, NOT_READY); + gpr_atm_rel_store(&r->writest.state, NOT_READY); + gpr_mu_init(&r->set_state_mu); + gpr_mu_init(&r->watcher_mu); + gpr_atm_rel_store(&r->shutdown, 0); + r->fd = fd; + r->watchers = NULL; + r->watcher_count = 0; + r->watcher_capacity = 0; + grpc_pollset_add_fd(grpc_backup_pollset(), r); + return r; +} + +int grpc_fd_is_orphaned(grpc_fd *fd) { + return (gpr_atm_acq_load(&fd->refst) & 1) == 0; +} + +static void wake_watchers(grpc_fd *fd) { + size_t i, n; + gpr_mu_lock(&fd->watcher_mu); + n = fd->watcher_count; + for (i = 0; i < n; i++) { + grpc_pollset_force_kick(fd->watchers[i]); + } + gpr_mu_unlock(&fd->watcher_mu); +} + +void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) { + fd->on_done = on_done ? on_done : do_nothing; + fd->on_done_user_data = user_data; + ref_by(fd, 1); /* remove active status, but keep referenced */ + wake_watchers(fd); + close(fd->fd); + unref_by(fd, 2); /* drop the reference */ +} + +/* increment refcount by two to avoid changing the orphan bit */ +void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); } + +void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); } + +typedef struct { + grpc_iomgr_cb_func cb; + void *arg; +} callback; + +static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success, + int allow_synchronous_callback) { + if (allow_synchronous_callback) { + cb(arg, success); + } else { + grpc_iomgr_add_delayed_callback(cb, arg, success); + } +} + +static void make_callbacks(callback *callbacks, size_t n, int success, + int allow_synchronous_callback) { + size_t i; + for (i = 0; i < n; i++) { + make_callback(callbacks[i].cb, callbacks[i].arg, success, + allow_synchronous_callback); + } +} + +static void notify_on(grpc_fd *fd, grpc_fd_state *st, grpc_iomgr_cb_func cb, + void *arg, int allow_synchronous_callback) { + switch ((enum descriptor_state)gpr_atm_acq_load(&st->state)) { + case NOT_READY: + /* There is no race if the descriptor is already ready, so we skip + the interlocked op in that case. As long as the app doesn't + try to set the same upcall twice (which it shouldn't) then + oldval should never be anything other than READY or NOT_READY. We + don't + check for user error on the fast path. */ + st->cb = cb; + st->cb_arg = arg; + if (gpr_atm_rel_cas(&st->state, NOT_READY, WAITING)) { + /* swap was successful -- the closure will run after the next + set_ready call. NOTE: we don't have an ABA problem here, + since we should never have concurrent calls to the same + notify_on function. */ + wake_watchers(fd); + return; + } + /* swap was unsuccessful due to an intervening set_ready call. + Fall through to the READY code below */ + case READY: + assert(gpr_atm_acq_load(&st->state) == READY); + gpr_atm_rel_store(&st->state, NOT_READY); + make_callback(cb, arg, !gpr_atm_acq_load(&fd->shutdown), + allow_synchronous_callback); + return; + case WAITING: + /* upcallptr was set to a different closure. This is an error! */ + gpr_log(GPR_ERROR, + "User called a notify_on function with a previous callback still " + "pending"); + abort(); + } + gpr_log(GPR_ERROR, "Corrupt memory in &st->state"); + abort(); +} + +static void set_ready_locked(grpc_fd_state *st, callback *callbacks, + size_t *ncallbacks) { + callback *c; + + switch ((enum descriptor_state)gpr_atm_acq_load(&st->state)) { + case NOT_READY: + if (gpr_atm_rel_cas(&st->state, NOT_READY, READY)) { + /* swap was successful -- the closure will run after the next + notify_on call. */ + return; + } + /* swap was unsuccessful due to an intervening set_ready call. + Fall through to the WAITING code below */ + case WAITING: + assert(gpr_atm_acq_load(&st->state) == WAITING); + c = &callbacks[(*ncallbacks)++]; + c->cb = st->cb; + c->arg = st->cb_arg; + gpr_atm_rel_store(&st->state, NOT_READY); + return; + case READY: + /* duplicate ready, ignore */ + return; + } +} + +static void set_ready(grpc_fd *fd, grpc_fd_state *st, + int allow_synchronous_callback) { + /* only one set_ready can be active at once (but there may be a racing + notify_on) */ + int success; + callback cb; + size_t ncb = 0; + gpr_mu_lock(&fd->set_state_mu); + set_ready_locked(st, &cb, &ncb); + gpr_mu_unlock(&fd->set_state_mu); + success = !gpr_atm_acq_load(&fd->shutdown); + make_callbacks(&cb, ncb, success, allow_synchronous_callback); +} + +void grpc_fd_shutdown(grpc_fd *fd) { + callback cb[2]; + size_t ncb = 0; + gpr_mu_lock(&fd->set_state_mu); + GPR_ASSERT(!gpr_atm_acq_load(&fd->shutdown)); + gpr_atm_rel_store(&fd->shutdown, 1); + set_ready_locked(&fd->readst, cb, &ncb); + set_ready_locked(&fd->writest, cb, &ncb); + gpr_mu_unlock(&fd->set_state_mu); + make_callbacks(cb, ncb, 0, 0); +} + +void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_cb_func read_cb, + void *read_cb_arg) { + notify_on(fd, &fd->readst, read_cb, read_cb_arg, 0); +} + +void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, + void *write_cb_arg) { + notify_on(fd, &fd->writest, write_cb, write_cb_arg, 0); +} + +gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, + gpr_uint32 read_mask, gpr_uint32 write_mask) { + /* keep track of pollers that have requested our events, in case they change + */ + gpr_mu_lock(&fd->watcher_mu); + if (fd->watcher_capacity == fd->watcher_count) { + fd->watcher_capacity = + GPR_MAX(fd->watcher_capacity + 8, fd->watcher_capacity * 3 / 2); + fd->watchers = gpr_realloc(fd->watchers, + fd->watcher_capacity * sizeof(grpc_pollset *)); + } + fd->watchers[fd->watcher_count++] = pollset; + gpr_mu_unlock(&fd->watcher_mu); + + return (gpr_atm_acq_load(&fd->readst.state) != READY ? read_mask : 0) | + (gpr_atm_acq_load(&fd->writest.state) != READY ? write_mask : 0); +} + +void grpc_fd_end_poll(grpc_fd *fd, grpc_pollset *pollset) { + size_t r, w, n; + + gpr_mu_lock(&fd->watcher_mu); + n = fd->watcher_count; + for (r = 0, w = 0; r < n; r++) { + if (fd->watchers[r] == pollset) { + fd->watcher_count--; + continue; + } + fd->watchers[w++] = fd->watchers[r]; + } + gpr_mu_unlock(&fd->watcher_mu); +} + +void grpc_fd_become_readable(grpc_fd *fd, int allow_synchronous_callback) { + set_ready(fd, &fd->readst, allow_synchronous_callback); +} + +void grpc_fd_become_writable(grpc_fd *fd, int allow_synchronous_callback) { + set_ready(fd, &fd->writest, allow_synchronous_callback); +} diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h new file mode 100644 index 00000000000..232de0c3e08 --- /dev/null +++ b/src/core/iomgr/fd_posix.h @@ -0,0 +1,138 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GRPC_INTERNAL_IOMGR_FD_POSIX_H_ +#define __GRPC_INTERNAL_IOMGR_FD_POSIX_H_ + +#include "src/core/iomgr/iomgr.h" +#include "src/core/iomgr/pollset.h" +#include +#include +#include + +typedef struct { + grpc_iomgr_cb_func cb; + void *cb_arg; + int success; + gpr_atm state; +} grpc_fd_state; + +typedef struct grpc_fd { + int fd; + /* refst format: + bit0: 1=active/0=orphaned + bit1-n: refcount + meaning that mostly we ref by two to avoid altering the orphaned bit, + and just unref by 1 when we're ready to flag the object as orphaned */ + gpr_atm refst; + + gpr_mu set_state_mu; + gpr_atm shutdown; + + gpr_mu watcher_mu; + grpc_pollset **watchers; + size_t watcher_count; + size_t watcher_capacity; + + grpc_fd_state readst; + grpc_fd_state writest; + + grpc_iomgr_cb_func on_done; + void *on_done_user_data; +} grpc_fd; + +/* Create a wrapped file descriptor. + Requires fd is a non-blocking file descriptor. + This takes ownership of closing fd. */ +grpc_fd *grpc_fd_create(int fd); + +/* Releases fd to be asynchronously destroyed. + on_done is called when the underlying file descriptor is definitely close()d. + If on_done is NULL, no callback will be made. + Requires: *fd initialized; no outstanding notify_on_read or + notify_on_write. */ +void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data); + +/* Begin polling on an fd. + Registers that the given pollset is interested in this fd - so that if read + or writability interest changes, the pollset can be kicked to pick up that + new interest. + Return value is: + (fd_needs_read? read_mask : 0) | (fd_needs_write? write_mask : 0) + i.e. a combination of read_mask and write_mask determined by the fd's current + interest in said events. + Polling strategies that do not need to alter their behavior depending on the + fd's current interest (such as epoll) do not need to call this function. */ +gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, + gpr_uint32 read_mask, gpr_uint32 write_mask); +/* Complete polling previously started with grpc_fd_begin_poll */ +void grpc_fd_end_poll(grpc_fd *fd, grpc_pollset *pollset); + +/* Return 1 if this fd is orphaned, 0 otherwise */ +int grpc_fd_is_orphaned(grpc_fd *fd); + +/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */ +void grpc_fd_shutdown(grpc_fd *fd); + +/* Register read interest, causing read_cb to be called once when fd becomes + readable, on deadline specified by deadline, or on shutdown triggered by + grpc_fd_shutdown. + read_cb will be called with read_cb_arg when *fd becomes readable. + read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable, + GRPC_CALLBACK_TIMED_OUT if the call timed out, + and CANCELLED if the call was cancelled. + + Requires:This method must not be called before the read_cb for any previous + call runs. Edge triggered events are used whenever they are supported by the + underlying platform. This means that users must drain fd in read_cb before + calling notify_on_read again. Users are also expected to handle spurious + events, i.e read_cb is called while nothing can be readable from fd */ +void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_cb_func read_cb, + void *read_cb_arg); + +/* Exactly the same semantics as above, except based on writable events. */ +void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, + void *write_cb_arg); + +/* Notification from the poller to an fd that it has become readable or + writable. + If allow_synchronous_callback is 1, allow running the fd callback inline + in this callstack, otherwise register an asynchronous callback and return */ +void grpc_fd_become_readable(grpc_fd *fd, int allow_synchronous_callback); +void grpc_fd_become_writable(grpc_fd *fd, int allow_synchronous_callback); + +/* Reference counting for fds */ +void grpc_fd_ref(grpc_fd *fd); +void grpc_fd_unref(grpc_fd *fd); + +#endif /* __GRPC_INTERNAL_IOMGR_FD_POSIX_H_ */ diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c new file mode 100644 index 00000000000..03f56a50a32 --- /dev/null +++ b/src/core/iomgr/iomgr.c @@ -0,0 +1,204 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/iomgr/iomgr.h" + +#include + +#include "src/core/iomgr/iomgr_internal.h" +#include "src/core/iomgr/alarm_internal.h" +#include +#include +#include +#include + +typedef struct delayed_callback { + grpc_iomgr_cb_func cb; + void *cb_arg; + int success; + struct delayed_callback *next; +} delayed_callback; + +static gpr_mu g_mu; +static gpr_cv g_cv; +static delayed_callback *g_cbs_head = NULL; +static delayed_callback *g_cbs_tail = NULL; +static int g_shutdown; +static int g_refs; +static gpr_event g_background_callback_executor_done; + +/* Execute followup callbacks continuously. + Other threads may check in and help during pollset_work() */ +static void background_callback_executor(void *ignored) { + gpr_mu_lock(&g_mu); + while (!g_shutdown) { + gpr_timespec deadline = gpr_inf_future; + if (g_cbs_head) { + delayed_callback *cb = g_cbs_head; + g_cbs_head = cb->next; + if (!g_cbs_head) g_cbs_tail = NULL; + gpr_mu_unlock(&g_mu); + cb->cb(cb->cb_arg, cb->success); + gpr_free(cb); + gpr_mu_lock(&g_mu); + } else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) { + } else { + gpr_cv_wait(&g_cv, &g_mu, deadline); + } + } + gpr_mu_unlock(&g_mu); + gpr_event_set(&g_background_callback_executor_done, (void *)1); +} + +void grpc_kick_poller() { gpr_cv_broadcast(&g_cv); } + +void grpc_iomgr_init() { + gpr_thd_id id; + gpr_mu_init(&g_mu); + gpr_cv_init(&g_cv); + grpc_alarm_list_init(gpr_now()); + g_refs = 0; + grpc_iomgr_platform_init(); + gpr_event_init(&g_background_callback_executor_done); + gpr_thd_new(&id, background_callback_executor, NULL, NULL); +} + +void grpc_iomgr_shutdown() { + delayed_callback *cb; + gpr_timespec shutdown_deadline = + gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); + + grpc_iomgr_platform_shutdown(); + + gpr_mu_lock(&g_mu); + g_shutdown = 1; + while (g_cbs_head || g_refs) { + gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs, + g_cbs_head ? " and executing final callbacks" : ""); + while (g_cbs_head) { + cb = g_cbs_head; + g_cbs_head = cb->next; + if (!g_cbs_head) g_cbs_tail = NULL; + gpr_mu_unlock(&g_mu); + + cb->cb(cb->cb_arg, 0); + gpr_free(cb); + gpr_mu_lock(&g_mu); + } + if (g_refs) { + if (gpr_cv_wait(&g_cv, &g_mu, shutdown_deadline) && g_cbs_head == NULL) { + gpr_log(GPR_DEBUG, + "Failed to free %d iomgr objects before shutdown deadline: " + "memory leaks are likely", + g_refs); + break; + } + } + } + gpr_mu_unlock(&g_mu); + + gpr_event_wait(&g_background_callback_executor_done, gpr_inf_future); + + grpc_alarm_list_shutdown(); + gpr_mu_destroy(&g_mu); + gpr_cv_destroy(&g_cv); +} + +void grpc_iomgr_ref() { + gpr_mu_lock(&g_mu); + ++g_refs; + gpr_mu_unlock(&g_mu); +} + +void grpc_iomgr_unref() { + gpr_mu_lock(&g_mu); + if (0 == --g_refs) { + gpr_cv_signal(&g_cv); + } + gpr_mu_unlock(&g_mu); +} + +void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg, + int success) { + delayed_callback *dcb = gpr_malloc(sizeof(delayed_callback)); + dcb->cb = cb; + dcb->cb_arg = cb_arg; + dcb->success = success; + gpr_mu_lock(&g_mu); + dcb->next = NULL; + if (!g_cbs_tail) { + g_cbs_head = g_cbs_tail = dcb; + } else { + g_cbs_tail->next = dcb; + g_cbs_tail = dcb; + } + gpr_cv_signal(&g_cv); + gpr_mu_unlock(&g_mu); +} + +void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg) { + grpc_iomgr_add_delayed_callback(cb, cb_arg, 1); +} + +int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) { + int n = 0; + gpr_mu *retake_mu = NULL; + delayed_callback *cb; + for (;;) { + /* check for new work */ + if (!gpr_mu_trylock(&g_mu)) { + break; + } + cb = g_cbs_head; + if (!cb) { + gpr_mu_unlock(&g_mu); + break; + } + g_cbs_head = cb->next; + if (!g_cbs_head) g_cbs_tail = NULL; + gpr_mu_unlock(&g_mu); + /* if we have a mutex to drop, do so before executing work */ + if (drop_mu) { + gpr_mu_unlock(drop_mu); + retake_mu = drop_mu; + drop_mu = NULL; + } + cb->cb(cb->cb_arg, success && cb->success); + gpr_free(cb); + n++; + } + if (retake_mu) { + gpr_mu_lock(retake_mu); + } + return n; +} diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h index cf39f947bc2..16991a9b90e 100644 --- a/src/core/iomgr/iomgr.h +++ b/src/core/iomgr/iomgr.h @@ -34,17 +34,8 @@ #ifndef __GRPC_INTERNAL_IOMGR_IOMGR_H__ #define __GRPC_INTERNAL_IOMGR_IOMGR_H__ -/* Status passed to callbacks for grpc_em_fd_notify_on_read and - grpc_em_fd_notify_on_write. */ -typedef enum grpc_em_cb_status { - GRPC_CALLBACK_SUCCESS = 0, - GRPC_CALLBACK_TIMED_OUT, - GRPC_CALLBACK_CANCELLED, - GRPC_CALLBACK_DO_NOT_USE -} grpc_iomgr_cb_status; - /* gRPC Callback definition */ -typedef void (*grpc_iomgr_cb_func)(void *arg, grpc_iomgr_cb_status status); +typedef void (*grpc_iomgr_cb_func)(void *arg, int success); void grpc_iomgr_init(); void grpc_iomgr_shutdown(); diff --git a/src/core/iomgr/iomgr_libevent_use_threads.c b/src/core/iomgr/iomgr_internal.h similarity index 67% rename from src/core/iomgr/iomgr_libevent_use_threads.c rename to src/core/iomgr/iomgr_internal.h index af449342f0c..5f72542777d 100644 --- a/src/core/iomgr/iomgr_libevent_use_threads.c +++ b/src/core/iomgr/iomgr_internal.h @@ -31,26 +31,21 @@ * */ -/* Posix grpc event manager support code. */ -#include +#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_INTERNAL_H_ +#define __GRPC_INTERNAL_IOMGR_IOMGR_INTERNAL_H_ + +#include "src/core/iomgr/iomgr.h" +#include "src/core/iomgr/iomgr_internal.h" #include -#include -static int error_code = 0; -static gpr_once threads_once = GPR_ONCE_INIT; -static void evthread_threads_initialize(void) { - error_code = evthread_use_pthreads(); - if (error_code) { - gpr_log(GPR_ERROR, "Failed to initialize libevent thread support!"); - } -} +int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success); +void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg, + int success); + +void grpc_iomgr_ref(); +void grpc_iomgr_unref(); + +void grpc_iomgr_platform_init(); +void grpc_iomgr_platform_shutdown(); -/* Notify LibEvent that Posix pthread is used. */ -int evthread_use_threads() { - gpr_once_init(&threads_once, &evthread_threads_initialize); - /* For Pthreads or Windows threads, Libevent provides simple APIs to set - mutexes and conditional variables to support cross thread operations. - For other platforms, LibEvent provide callback APIs to hook mutexes and - conditional variables. */ - return error_code; -} +#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_INTERNAL_H_ */ diff --git a/src/core/iomgr/iomgr_libevent.c b/src/core/iomgr/iomgr_libevent.c deleted file mode 100644 index 6188ab2749c..00000000000 --- a/src/core/iomgr/iomgr_libevent.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/iomgr/iomgr_libevent.h" - -#include -#include - -#include "src/core/iomgr/alarm.h" -#include "src/core/iomgr/alarm_internal.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#define ALARM_TRIGGER_INIT ((gpr_atm)0) -#define ALARM_TRIGGER_INCREMENT ((gpr_atm)1) -#define DONE_SHUTDOWN ((void *)1) - -#define POLLER_ID_INVALID ((gpr_atm)-1) - -/* Global data */ -struct event_base *g_event_base; -gpr_mu grpc_iomgr_mu; -gpr_cv grpc_iomgr_cv; -static grpc_libevent_activation_data *g_activation_queue; -static int g_num_pollers; -static int g_num_fds; -static int g_num_address_resolutions; -static gpr_timespec g_last_poll_completed; -static int g_shutdown_backup_poller; -static gpr_event g_backup_poller_done; -/* activated to break out of the event loop early */ -static struct event *g_timeout_ev; -/* activated to safely break polling from other threads */ -static struct event *g_break_ev; -static grpc_fd *g_fds_to_free; - -int evthread_use_threads(void); -static void grpc_fd_impl_destroy(grpc_fd *impl); - -void grpc_iomgr_ref_address_resolution(int delta) { - gpr_mu_lock(&grpc_iomgr_mu); - GPR_ASSERT(!g_shutdown_backup_poller); - g_num_address_resolutions += delta; - if (0 == g_num_address_resolutions) { - gpr_cv_broadcast(&grpc_iomgr_cv); - } - gpr_mu_unlock(&grpc_iomgr_mu); -} - -/* If anything is in the work queue, process one item and return 1. - Return 0 if there were no work items to complete. - Requires grpc_iomgr_mu locked, may unlock and relock during the call. */ -static int maybe_do_queue_work() { - grpc_libevent_activation_data *work = g_activation_queue; - - if (work == NULL) return 0; - - if (work->next == work) { - g_activation_queue = NULL; - } else { - g_activation_queue = work->next; - g_activation_queue->prev = work->prev; - g_activation_queue->next->prev = g_activation_queue->prev->next = - g_activation_queue; - } - work->next = work->prev = NULL; - /* force status to cancelled from ok when shutting down */ - if (g_shutdown_backup_poller && work->status == GRPC_CALLBACK_SUCCESS) { - work->status = GRPC_CALLBACK_CANCELLED; - } - gpr_mu_unlock(&grpc_iomgr_mu); - - work->cb(work->arg, work->status); - - gpr_mu_lock(&grpc_iomgr_mu); - return 1; -} - -/* Break out of the event loop on timeout */ -static void timer_callback(int fd, short events, void *context) { - event_base_loopbreak((struct event_base *)context); -} - -static void break_callback(int fd, short events, void *context) { - event_base_loopbreak((struct event_base *)context); -} - -static void free_fd_list(grpc_fd *impl) { - while (impl != NULL) { - grpc_fd *current = impl; - impl = impl->next; - grpc_fd_impl_destroy(current); - current->on_done(current->on_done_user_data, GRPC_CALLBACK_SUCCESS); - gpr_free(current); - } -} - -static void maybe_free_fds() { - if (g_fds_to_free) { - free_fd_list(g_fds_to_free); - g_fds_to_free = NULL; - } -} - -void grpc_kick_poller() { event_active(g_break_ev, EV_READ, 0); } - -/* Spend some time doing polling and libevent maintenance work if no other - thread is. This includes both polling for events and destroying/closing file - descriptor objects. - Returns 1 if polling was performed, 0 otherwise. - Requires grpc_iomgr_mu locked, may unlock and relock during the call. */ -static int maybe_do_polling_work(struct timeval delay) { - int status; - - if (g_num_pollers) return 0; - - g_num_pollers = 1; - - maybe_free_fds(); - - gpr_mu_unlock(&grpc_iomgr_mu); - - event_add(g_timeout_ev, &delay); - status = event_base_loop(g_event_base, EVLOOP_ONCE); - if (status < 0) { - gpr_log(GPR_ERROR, "event polling loop stops with error status %d", status); - } - event_del(g_timeout_ev); - - gpr_mu_lock(&grpc_iomgr_mu); - maybe_free_fds(); - - g_num_pollers = 0; - gpr_cv_broadcast(&grpc_iomgr_cv); - return 1; -} - -static int maybe_do_alarm_work(gpr_timespec now, gpr_timespec next) { - int r = 0; - if (gpr_time_cmp(next, now) < 0) { - gpr_mu_unlock(&grpc_iomgr_mu); - r = grpc_alarm_check(now); - gpr_mu_lock(&grpc_iomgr_mu); - } - return r; -} - -int grpc_iomgr_work(gpr_timespec deadline) { - gpr_timespec now = gpr_now(); - gpr_timespec next = grpc_alarm_list_next_timeout(); - gpr_timespec delay_timespec = gpr_time_sub(deadline, now); - /* poll for no longer than one second */ - gpr_timespec max_delay = gpr_time_from_seconds(1); - struct timeval delay; - - if (gpr_time_cmp(delay_timespec, gpr_time_0) <= 0) { - return 0; - } - - if (gpr_time_cmp(delay_timespec, max_delay) > 0) { - delay_timespec = max_delay; - } - - /* Adjust delay to account for the next alarm, if applicable. */ - delay_timespec = gpr_time_min( - delay_timespec, gpr_time_sub(grpc_alarm_list_next_timeout(), now)); - - delay = gpr_timeval_from_timespec(delay_timespec); - - if (maybe_do_queue_work() || maybe_do_alarm_work(now, next) || - maybe_do_polling_work(delay)) { - g_last_poll_completed = gpr_now(); - return 1; - } - - return 0; -} - -static void backup_poller_thread(void *p) { - int backup_poller_engaged = 0; - /* allow no pollers for 100 milliseconds, then engage backup polling */ - gpr_timespec allow_no_pollers = gpr_time_from_millis(100); - - gpr_mu_lock(&grpc_iomgr_mu); - while (!g_shutdown_backup_poller) { - if (g_num_pollers == 0) { - gpr_timespec now = gpr_now(); - gpr_timespec time_until_engage = gpr_time_sub( - allow_no_pollers, gpr_time_sub(now, g_last_poll_completed)); - if (gpr_time_cmp(time_until_engage, gpr_time_0) <= 0) { - if (!backup_poller_engaged) { - gpr_log(GPR_DEBUG, "No pollers for a while - engaging backup poller"); - backup_poller_engaged = 1; - } - if (!maybe_do_queue_work()) { - gpr_timespec next = grpc_alarm_list_next_timeout(); - if (!maybe_do_alarm_work(now, next)) { - gpr_timespec deadline = - gpr_time_min(next, gpr_time_add(now, gpr_time_from_seconds(1))); - maybe_do_polling_work( - gpr_timeval_from_timespec(gpr_time_sub(deadline, now))); - } - } - } else { - if (backup_poller_engaged) { - gpr_log(GPR_DEBUG, "Backup poller disengaged"); - backup_poller_engaged = 0; - } - gpr_mu_unlock(&grpc_iomgr_mu); - gpr_sleep_until(gpr_time_add(now, time_until_engage)); - gpr_mu_lock(&grpc_iomgr_mu); - } - } else { - if (backup_poller_engaged) { - gpr_log(GPR_DEBUG, "Backup poller disengaged"); - backup_poller_engaged = 0; - } - gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, gpr_inf_future); - } - } - gpr_mu_unlock(&grpc_iomgr_mu); - - gpr_event_set(&g_backup_poller_done, (void *)1); -} - -void grpc_iomgr_init() { - gpr_thd_id backup_poller_id; - - if (evthread_use_threads() != 0) { - gpr_log(GPR_ERROR, "Failed to initialize libevent thread support!"); - abort(); - } - - grpc_alarm_list_init(gpr_now()); - - gpr_mu_init(&grpc_iomgr_mu); - gpr_cv_init(&grpc_iomgr_cv); - g_activation_queue = NULL; - g_num_pollers = 0; - g_num_fds = 0; - g_num_address_resolutions = 0; - g_last_poll_completed = gpr_now(); - g_shutdown_backup_poller = 0; - g_fds_to_free = NULL; - - gpr_event_init(&g_backup_poller_done); - - g_event_base = NULL; - g_timeout_ev = NULL; - g_break_ev = NULL; - - g_event_base = event_base_new(); - if (!g_event_base) { - gpr_log(GPR_ERROR, "Failed to create the event base"); - abort(); - } - - if (evthread_make_base_notifiable(g_event_base) != 0) { - gpr_log(GPR_ERROR, "Couldn't make event base notifiable cross threads!"); - abort(); - } - - g_timeout_ev = evtimer_new(g_event_base, timer_callback, g_event_base); - g_break_ev = event_new(g_event_base, -1, EV_READ | EV_PERSIST, break_callback, - g_event_base); - - event_add(g_break_ev, NULL); - - gpr_thd_new(&backup_poller_id, backup_poller_thread, NULL, NULL); -} - -void grpc_iomgr_shutdown() { - gpr_timespec fd_shutdown_deadline = - gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); - - /* broadcast shutdown */ - gpr_mu_lock(&grpc_iomgr_mu); - while (g_num_fds > 0 || g_num_address_resolutions > 0) { - gpr_log(GPR_INFO, - "waiting for %d fds and %d name resolutions to be destroyed before " - "closing event manager", - g_num_fds, g_num_address_resolutions); - if (gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, fd_shutdown_deadline)) { - gpr_log(GPR_ERROR, - "not all fds or name resolutions destroyed before shutdown " - "deadline: memory leaks " - "are likely"); - break; - } else if (g_num_fds == 0 && g_num_address_resolutions == 0) { - gpr_log(GPR_INFO, "all fds closed, all name resolutions finished"); - } - } - - g_shutdown_backup_poller = 1; - gpr_cv_broadcast(&grpc_iomgr_cv); - gpr_mu_unlock(&grpc_iomgr_mu); - - gpr_event_wait(&g_backup_poller_done, gpr_inf_future); - - grpc_alarm_list_shutdown(); - - /* drain pending work */ - gpr_mu_lock(&grpc_iomgr_mu); - while (maybe_do_queue_work()) - ; - gpr_mu_unlock(&grpc_iomgr_mu); - - free_fd_list(g_fds_to_free); - - /* complete shutdown */ - gpr_mu_destroy(&grpc_iomgr_mu); - gpr_cv_destroy(&grpc_iomgr_cv); - - if (g_timeout_ev != NULL) { - event_free(g_timeout_ev); - } - - if (g_break_ev != NULL) { - event_free(g_break_ev); - } - - if (g_event_base != NULL) { - event_base_free(g_event_base); - g_event_base = NULL; - } -} - -static void add_task(grpc_libevent_activation_data *adata) { - gpr_mu_lock(&grpc_iomgr_mu); - if (g_activation_queue) { - adata->next = g_activation_queue; - adata->prev = adata->next->prev; - adata->next->prev = adata->prev->next = adata; - } else { - g_activation_queue = adata; - adata->next = adata->prev = adata; - } - gpr_cv_broadcast(&grpc_iomgr_cv); - gpr_mu_unlock(&grpc_iomgr_mu); -} - -static void grpc_fd_impl_destroy(grpc_fd *impl) { - grpc_em_task_activity_type type; - grpc_libevent_activation_data *adata; - - for (type = GRPC_EM_TA_READ; type < GRPC_EM_TA_COUNT; type++) { - adata = &(impl->task.activation[type]); - GPR_ASSERT(adata->next == NULL); - if (adata->ev != NULL) { - event_free(adata->ev); - adata->ev = NULL; - } - } - - if (impl->shutdown_ev != NULL) { - event_free(impl->shutdown_ev); - impl->shutdown_ev = NULL; - } - gpr_mu_destroy(&impl->mu); - close(impl->fd); -} - -/* Proxy callback to call a gRPC read/write callback */ -static void em_fd_cb(int fd, short what, void *arg /*=em_fd*/) { - grpc_fd *em_fd = arg; - grpc_iomgr_cb_status status = GRPC_CALLBACK_SUCCESS; - int run_read_cb = 0; - int run_write_cb = 0; - grpc_libevent_activation_data *rdata, *wdata; - - gpr_mu_lock(&em_fd->mu); - if (em_fd->shutdown_started) { - status = GRPC_CALLBACK_CANCELLED; - } else if (status == GRPC_CALLBACK_SUCCESS && (what & EV_TIMEOUT)) { - status = GRPC_CALLBACK_TIMED_OUT; - /* TODO(klempner): This is broken if we are monitoring both read and write - events on the same fd -- generating a spurious event is okay, but - generating a spurious timeout is not. */ - what |= (EV_READ | EV_WRITE); - } - - if (what & EV_READ) { - switch (em_fd->read_state) { - case GRPC_FD_WAITING: - run_read_cb = 1; - em_fd->read_state = GRPC_FD_IDLE; - break; - case GRPC_FD_IDLE: - case GRPC_FD_CACHED: - em_fd->read_state = GRPC_FD_CACHED; - } - } - if (what & EV_WRITE) { - switch (em_fd->write_state) { - case GRPC_FD_WAITING: - run_write_cb = 1; - em_fd->write_state = GRPC_FD_IDLE; - break; - case GRPC_FD_IDLE: - case GRPC_FD_CACHED: - em_fd->write_state = GRPC_FD_CACHED; - } - } - - if (run_read_cb) { - rdata = &(em_fd->task.activation[GRPC_EM_TA_READ]); - rdata->status = status; - add_task(rdata); - } else if (run_write_cb) { - wdata = &(em_fd->task.activation[GRPC_EM_TA_WRITE]); - wdata->status = status; - add_task(wdata); - } - gpr_mu_unlock(&em_fd->mu); -} - -static void em_fd_shutdown_cb(int fd, short what, void *arg /*=em_fd*/) { - /* TODO(klempner): This could just run directly in the calling thread, except - that libevent's handling of event_active() on an event which is already in - flight on a different thread is racy and easily triggers TSAN. - */ - grpc_fd *impl = arg; - gpr_mu_lock(&impl->mu); - impl->shutdown_started = 1; - if (impl->read_state == GRPC_FD_WAITING) { - event_active(impl->task.activation[GRPC_EM_TA_READ].ev, EV_READ, 1); - } - if (impl->write_state == GRPC_FD_WAITING) { - event_active(impl->task.activation[GRPC_EM_TA_WRITE].ev, EV_WRITE, 1); - } - gpr_mu_unlock(&impl->mu); -} - -grpc_fd *grpc_fd_create(int fd) { - int flags; - grpc_libevent_activation_data *rdata, *wdata; - grpc_fd *impl = gpr_malloc(sizeof(grpc_fd)); - - gpr_mu_lock(&grpc_iomgr_mu); - g_num_fds++; - gpr_mu_unlock(&grpc_iomgr_mu); - - impl->shutdown_ev = NULL; - gpr_mu_init(&impl->mu); - - flags = fcntl(fd, F_GETFL, 0); - GPR_ASSERT((flags & O_NONBLOCK) != 0); - - impl->task.type = GRPC_EM_TASK_FD; - impl->fd = fd; - - rdata = &(impl->task.activation[GRPC_EM_TA_READ]); - rdata->ev = NULL; - rdata->cb = NULL; - rdata->arg = NULL; - rdata->status = GRPC_CALLBACK_SUCCESS; - rdata->prev = NULL; - rdata->next = NULL; - - wdata = &(impl->task.activation[GRPC_EM_TA_WRITE]); - wdata->ev = NULL; - wdata->cb = NULL; - wdata->arg = NULL; - wdata->status = GRPC_CALLBACK_SUCCESS; - wdata->prev = NULL; - wdata->next = NULL; - - impl->read_state = GRPC_FD_IDLE; - impl->write_state = GRPC_FD_IDLE; - - impl->shutdown_started = 0; - impl->next = NULL; - - /* TODO(chenw): detect platforms where only level trigger is supported, - and set the event to non-persist. */ - rdata->ev = event_new(g_event_base, impl->fd, EV_ET | EV_PERSIST | EV_READ, - em_fd_cb, impl); - GPR_ASSERT(rdata->ev); - - wdata->ev = event_new(g_event_base, impl->fd, EV_ET | EV_PERSIST | EV_WRITE, - em_fd_cb, impl); - GPR_ASSERT(wdata->ev); - - impl->shutdown_ev = - event_new(g_event_base, -1, EV_READ, em_fd_shutdown_cb, impl); - GPR_ASSERT(impl->shutdown_ev); - - return impl; -} - -static void do_nothing(void *ignored, grpc_iomgr_cb_status also_ignored) {} - -void grpc_fd_destroy(grpc_fd *impl, grpc_iomgr_cb_func on_done, - void *user_data) { - if (on_done == NULL) on_done = do_nothing; - - gpr_mu_lock(&grpc_iomgr_mu); - - /* Put the impl on the list to be destroyed by the poller. */ - impl->on_done = on_done; - impl->on_done_user_data = user_data; - impl->next = g_fds_to_free; - g_fds_to_free = impl; - /* TODO(ctiller): kick the poller so it destroys this fd promptly - (currently we may wait up to a second) */ - - g_num_fds--; - gpr_cv_broadcast(&grpc_iomgr_cv); - gpr_mu_unlock(&grpc_iomgr_mu); -} - -int grpc_fd_get(struct grpc_fd *em_fd) { return em_fd->fd; } - -/* TODO(chenw): should we enforce the contract that notify_on_read cannot be - called when the previously registered callback has not been called yet. */ -int grpc_fd_notify_on_read(grpc_fd *impl, grpc_iomgr_cb_func read_cb, - void *read_cb_arg, gpr_timespec deadline) { - int force_event = 0; - grpc_libevent_activation_data *rdata; - gpr_timespec delay_timespec = gpr_time_sub(deadline, gpr_now()); - struct timeval delay = gpr_timeval_from_timespec(delay_timespec); - struct timeval *delayp = - gpr_time_cmp(deadline, gpr_inf_future) ? &delay : NULL; - - rdata = &impl->task.activation[GRPC_EM_TA_READ]; - - gpr_mu_lock(&impl->mu); - rdata->cb = read_cb; - rdata->arg = read_cb_arg; - - force_event = (impl->shutdown_started || impl->read_state == GRPC_FD_CACHED); - impl->read_state = GRPC_FD_WAITING; - - if (force_event) { - event_active(rdata->ev, EV_READ, 1); - } else if (event_add(rdata->ev, delayp) == -1) { - gpr_mu_unlock(&impl->mu); - return 0; - } - gpr_mu_unlock(&impl->mu); - return 1; -} - -int grpc_fd_notify_on_write(grpc_fd *impl, grpc_iomgr_cb_func write_cb, - void *write_cb_arg, gpr_timespec deadline) { - int force_event = 0; - grpc_libevent_activation_data *wdata; - gpr_timespec delay_timespec = gpr_time_sub(deadline, gpr_now()); - struct timeval delay = gpr_timeval_from_timespec(delay_timespec); - struct timeval *delayp = - gpr_time_cmp(deadline, gpr_inf_future) ? &delay : NULL; - - wdata = &impl->task.activation[GRPC_EM_TA_WRITE]; - - gpr_mu_lock(&impl->mu); - wdata->cb = write_cb; - wdata->arg = write_cb_arg; - - force_event = (impl->shutdown_started || impl->write_state == GRPC_FD_CACHED); - impl->write_state = GRPC_FD_WAITING; - - if (force_event) { - event_active(wdata->ev, EV_WRITE, 1); - } else if (event_add(wdata->ev, delayp) == -1) { - gpr_mu_unlock(&impl->mu); - return 0; - } - gpr_mu_unlock(&impl->mu); - return 1; -} - -void grpc_fd_shutdown(grpc_fd *em_fd) { - event_active(em_fd->shutdown_ev, EV_READ, 1); -} - -/* Sometimes we want a followup callback: something to be added from the - current callback for the EM to invoke once this callback is complete. - This is implemented by inserting an entry into an EM queue. */ - -/* The following structure holds the field needed for adding the - followup callback. These are the argument for the followup callback, - the function to use for the followup callback, and the - activation data pointer used for the queues (to free in the CB) */ -struct followup_callback_arg { - grpc_iomgr_cb_func func; - void *cb_arg; - grpc_libevent_activation_data adata; -}; - -static void followup_proxy_callback(void *cb_arg, grpc_iomgr_cb_status status) { - struct followup_callback_arg *fcb_arg = cb_arg; - /* Invoke the function */ - fcb_arg->func(fcb_arg->cb_arg, status); - gpr_free(fcb_arg); -} - -void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg) { - grpc_libevent_activation_data *adptr; - struct followup_callback_arg *fcb_arg; - - fcb_arg = gpr_malloc(sizeof(*fcb_arg)); - /* Set up the activation data and followup callback argument structures */ - adptr = &fcb_arg->adata; - adptr->ev = NULL; - adptr->cb = followup_proxy_callback; - adptr->arg = fcb_arg; - adptr->status = GRPC_CALLBACK_SUCCESS; - adptr->prev = NULL; - adptr->next = NULL; - - fcb_arg->func = cb; - fcb_arg->cb_arg = cb_arg; - - /* Insert an activation data for the specified em */ - add_task(adptr); -} diff --git a/src/core/iomgr/iomgr_libevent.h b/src/core/iomgr/iomgr_libevent.h deleted file mode 100644 index 5c088006a0a..00000000000 --- a/src/core/iomgr/iomgr_libevent.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_LIBEVENT_H__ -#define __GRPC_INTERNAL_IOMGR_IOMGR_LIBEVENT_H__ - -#include "src/core/iomgr/iomgr.h" -#include -#include - -typedef struct grpc_fd grpc_fd; - -/* gRPC event manager task "base class". This is pretend-inheritance in C89. - This should be the first member of any actual grpc_em task type. - - Memory warning: expanding this will increase memory usage in any derived - class, so be careful. - - For generality, this base can be on multiple task queues and can have - multiple event callbacks registered. Not all "derived classes" will use - this feature. */ - -typedef enum grpc_libevent_task_type { - GRPC_EM_TASK_ALARM, - GRPC_EM_TASK_FD, - GRPC_EM_TASK_DO_NOT_USE -} grpc_libevent_task_type; - -/* Different activity types to shape the callback and queueing arrays */ -typedef enum grpc_em_task_activity_type { - GRPC_EM_TA_READ, /* use this also for single-type events */ - GRPC_EM_TA_WRITE, - GRPC_EM_TA_COUNT -} grpc_em_task_activity_type; - -/* Include the following #define for convenience for tasks like alarms that - only have a single type */ -#define GRPC_EM_TA_ONLY GRPC_EM_TA_READ - -typedef struct grpc_libevent_activation_data { - struct event *ev; /* event activated on this callback type */ - grpc_iomgr_cb_func cb; /* function pointer for callback */ - void *arg; /* argument passed to cb */ - - /* Hold the status associated with the callback when queued */ - grpc_iomgr_cb_status status; - /* Now set up to link activations into scheduler queues */ - struct grpc_libevent_activation_data *prev; - struct grpc_libevent_activation_data *next; -} grpc_libevent_activation_data; - -typedef struct grpc_libevent_task { - grpc_libevent_task_type type; - - /* Now have an array of activation data elements: one for each activity - type that could get activated */ - grpc_libevent_activation_data activation[GRPC_EM_TA_COUNT]; -} grpc_libevent_task; - -/* Initialize *em_fd. - Requires fd is a non-blocking file descriptor. - - This takes ownership of closing fd. - - Requires: *em_fd uninitialized. fd is a non-blocking file descriptor. */ -grpc_fd *grpc_fd_create(int fd); - -/* Cause *em_fd no longer to be initialized and closes the underlying fd. - on_done is called when the underlying file descriptor is definitely close()d. - If on_done is NULL, no callback will be made. - Requires: *em_fd initialized; no outstanding notify_on_read or - notify_on_write. */ -void grpc_fd_destroy(grpc_fd *em_fd, grpc_iomgr_cb_func on_done, - void *user_data); - -/* Returns the file descriptor associated with *em_fd. */ -int grpc_fd_get(grpc_fd *em_fd); - -/* Register read interest, causing read_cb to be called once when em_fd becomes - readable, on deadline specified by deadline, or on shutdown triggered by - grpc_fd_shutdown. - read_cb will be called with read_cb_arg when *em_fd becomes readable. - read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable, - GRPC_CALLBACK_TIMED_OUT if the call timed out, - and CANCELLED if the call was cancelled. - - Requires:This method must not be called before the read_cb for any previous - call runs. Edge triggered events are used whenever they are supported by the - underlying platform. This means that users must drain em_fd in read_cb before - calling notify_on_read again. Users are also expected to handle spurious - events, i.e read_cb is called while nothing can be readable from em_fd */ -int grpc_fd_notify_on_read(grpc_fd *em_fd, grpc_iomgr_cb_func read_cb, - void *read_cb_arg, gpr_timespec deadline); - -/* Exactly the same semantics as above, except based on writable events. */ -int grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, - void *write_cb_arg, gpr_timespec deadline); - -/* Cause any current and all future read/write callbacks to error out with - GRPC_CALLBACK_CANCELLED. */ -void grpc_fd_shutdown(grpc_fd *em_fd); - -/* =================== Event caching =================== - In order to not miss or double-return edges in the context of edge triggering - and multithreading, we need a per-fd caching layer in the eventmanager itself - to cache relevant events. - - There are two types of events we care about: calls to notify_on_[read|write] - and readable/writable events for the socket from eventfd. There are separate - event caches for read and write. - - There are three states: - 0. "waiting" -- There's been a call to notify_on_[read|write] which has not - had a corresponding event. In other words, we're waiting for an event so we - can run the callback. - 1. "idle" -- We are neither waiting nor have a cached event. - 2. "cached" -- There has been a read/write event without a waiting callback, - so we want to run the event next time the application calls - notify_on_[read|write]. - - The high level state diagram: - - +--------------------------------------------------------------------+ - | WAITING | IDLE | CACHED | - | | | | - | 1. --*-> 2. --+-> 3. --+\ - | | | <--+/ - | | | | - x+-- 6. 5. <-+-- 4. <-*-- | - | | | | - +--------------------------------------------------------------------+ - - Transitions right occur on read|write events. Transitions left occur on - notify_on_[read|write] events. - State transitions: - 1. Read|Write event while waiting -> run the callback and transition to idle. - 2. Read|Write event while idle -> transition to cached. - 3. Read|Write event with one already cached -> still cached. - 4. notify_on_[read|write] with event cached: run callback and transition to - idle. - 5. notify_on_[read|write] when idle: Store callback and transition to - waiting. - 6. notify_on_[read|write] when waiting: invalid. */ - -typedef enum grpc_fd_state { - GRPC_FD_WAITING = 0, - GRPC_FD_IDLE = 1, - GRPC_FD_CACHED = 2 -} grpc_fd_state; - -/* gRPC file descriptor handle. - The handle is used to register read/write callbacks to a file descriptor */ -struct grpc_fd { - grpc_libevent_task task; /* Base class, callbacks, queues, etc */ - int fd; /* File descriptor */ - - /* Note that the shutdown event is only needed as a workaround for libevent - not properly handling event_active on an in flight event. */ - struct event *shutdown_ev; /* activated to trigger shutdown */ - - /* protect shutdown_started|read_state|write_state and ensure barriers - between notify_on_[read|write] and read|write callbacks */ - gpr_mu mu; - int shutdown_started; /* 0 -> shutdown not started, 1 -> started */ - grpc_fd_state read_state; - grpc_fd_state write_state; - - /* descriptor delete list. These are destroyed during polling. */ - struct grpc_fd *next; - grpc_iomgr_cb_func on_done; - void *on_done_user_data; -}; - -void grpc_iomgr_ref_address_resolution(int delta); - -#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_LIBEVENT_H__ */ diff --git a/src/core/iomgr/pollset.c b/src/core/iomgr/iomgr_posix.c similarity index 89% rename from src/core/iomgr/pollset.c rename to src/core/iomgr/iomgr_posix.c index 62a0019eb33..ff9195ec1dc 100644 --- a/src/core/iomgr/pollset.c +++ b/src/core/iomgr/iomgr_posix.c @@ -31,7 +31,8 @@ * */ -#include "src/core/iomgr/pollset.h" +#include "src/core/iomgr/iomgr_posix.h" -void grpc_pollset_init(grpc_pollset *pollset) { pollset->unused = 0; } -void grpc_pollset_destroy(grpc_pollset *pollset) {} +void grpc_iomgr_platform_init() { grpc_pollset_global_init(); } + +void grpc_iomgr_platform_shutdown() { grpc_pollset_global_shutdown(); } diff --git a/src/core/iomgr/iomgr_completion_queue_interface.h b/src/core/iomgr/iomgr_posix.h similarity index 79% rename from src/core/iomgr/iomgr_completion_queue_interface.h rename to src/core/iomgr/iomgr_posix.h index 3c4efe773a7..ca5af3e5276 100644 --- a/src/core/iomgr/iomgr_completion_queue_interface.h +++ b/src/core/iomgr/iomgr_posix.h @@ -31,15 +31,12 @@ * */ -#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_COMPLETION_QUEUE_INTERFACE_H_ -#define __GRPC_INTERNAL_IOMGR_IOMGR_COMPLETION_QUEUE_INTERFACE_H_ +#ifndef __GRPC_INTERNAL_IOMGR_IOMGR_POSIX_H_ +#define __GRPC_INTERNAL_IOMGR_IOMGR_POSIX_H_ -/* Internals of iomgr that are exposed only to be used for completion queue - implementation */ +#include "src/core/iomgr/iomgr_internal.h" -extern gpr_mu grpc_iomgr_mu; -extern gpr_cv grpc_iomgr_cv; +void grpc_pollset_global_init(); +void grpc_pollset_global_shutdown(); -int grpc_iomgr_work(gpr_timespec deadline); - -#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_COMPLETION_QUEUE_INTERFACE_H_ */ +#endif /* __GRPC_INTERNAL_IOMGR_IOMGR_POSIX_H_ */ diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h index ba1a9d54296..7374a4ec131 100644 --- a/src/core/iomgr/pollset.h +++ b/src/core/iomgr/pollset.h @@ -34,18 +34,31 @@ #ifndef __GRPC_INTERNAL_IOMGR_POLLSET_H_ #define __GRPC_INTERNAL_IOMGR_POLLSET_H_ +#include + /* A grpc_pollset is a set of file descriptors that a higher level item is interested in. For example: - a server will typically keep a pollset containing all connected channels, so that it can find new calls to service - a completion queue might keep a pollset with an entry for each transport that is servicing a call that it's tracking */ -/* Eventually different implementations of iomgr will provide their own - grpc_pollset structs. As this is just a dummy wrapper to get the API in, - we just define a simple type here. */ -typedef struct { char unused; } grpc_pollset; + +#ifdef GPR_POSIX_SOCKET +#include "src/core/iomgr/pollset_posix.h" +#endif void grpc_pollset_init(grpc_pollset *pollset); 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. */ +int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline); + +/* Break a pollset out of polling work + Requires GRPC_POLLSET_MU(pollset) locked. */ +void grpc_pollset_kick(grpc_pollset *pollset); + #endif /* __GRPC_INTERNAL_IOMGR_POLLSET_H_ */ diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c new file mode 100644 index 00000000000..06c7a5a0dd3 --- /dev/null +++ b/src/core/iomgr/pollset_multipoller_with_poll_posix.c @@ -0,0 +1,237 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#ifdef GPR_POSIX_MULTIPOLL_WITH_POLL + +#include "src/core/iomgr/pollset_posix.h" + +#include +#include +#include +#include + +#include "src/core/iomgr/fd_posix.h" +#include "src/core/iomgr/iomgr_internal.h" +#include +#include +#include + +typedef struct { + /* all polled fds */ + size_t fd_count; + size_t fd_capacity; + grpc_fd **fds; + /* fds being polled by the current poller: parallel arrays of pollfd and the + * grpc_fd* that the pollfd was constructed from */ + size_t pfd_count; + size_t pfd_capacity; + grpc_fd **selfds; + struct pollfd *pfds; + /* fds that have been removed from the pollset explicitly */ + size_t del_count; + size_t del_capacity; + grpc_fd **dels; +} pollset_hdr; + +static void multipoll_with_poll_pollset_add_fd(grpc_pollset *pollset, + grpc_fd *fd) { + size_t i; + pollset_hdr *h = pollset->data.ptr; + /* TODO(ctiller): this is O(num_fds^2); maybe switch to a hash set here */ + for (i = 0; i < h->fd_count; i++) { + if (h->fds[i] == fd) return; + } + if (h->fd_count == h->fd_capacity) { + h->fd_capacity = GPR_MAX(h->fd_capacity + 8, h->fd_count * 3 / 2); + h->fds = gpr_realloc(h->fds, sizeof(grpc_fd *) * h->fd_capacity); + } + h->fds[h->fd_count++] = fd; + grpc_fd_ref(fd); +} + +static void multipoll_with_poll_pollset_del_fd(grpc_pollset *pollset, + grpc_fd *fd) { + /* will get removed next poll cycle */ + pollset_hdr *h = pollset->data.ptr; + if (h->del_count == h->del_capacity) { + h->del_capacity = GPR_MAX(h->del_capacity + 8, h->del_count * 3 / 2); + h->dels = gpr_realloc(h->dels, sizeof(grpc_fd *) * h->del_capacity); + } + h->dels[h->del_count++] = fd; + grpc_fd_ref(fd); +} + +static void end_polling(grpc_pollset *pollset) { + size_t i; + pollset_hdr *h; + h = pollset->data.ptr; + for (i = 1; i < h->pfd_count; i++) { + grpc_fd_end_poll(h->selfds[i], pollset); + } +} + +static int multipoll_with_poll_pollset_maybe_work( + grpc_pollset *pollset, gpr_timespec deadline, gpr_timespec now, + int allow_synchronous_callback) { + int timeout; + int r; + size_t i, np, nf, nd; + pollset_hdr *h; + + if (pollset->counter) { + return 0; + } + h = pollset->data.ptr; + if (gpr_time_cmp(deadline, gpr_inf_future) == 0) { + timeout = -1; + } else { + timeout = gpr_time_to_millis(gpr_time_sub(deadline, now)); + if (timeout <= 0) { + return 1; + } + } + if (h->pfd_capacity < h->fd_count + 1) { + h->pfd_capacity = GPR_MAX(h->pfd_capacity * 3 / 2, h->fd_count + 1); + gpr_free(h->pfds); + gpr_free(h->selfds); + h->pfds = gpr_malloc(sizeof(struct pollfd) * h->pfd_capacity); + h->selfds = gpr_malloc(sizeof(grpc_fd *) * h->pfd_capacity); + } + nf = 0; + np = 1; + h->pfds[0].fd = grpc_kick_read_fd(pollset); + h->pfds[0].events = POLLIN; + h->pfds[0].revents = POLLOUT; + for (i = 0; i < h->fd_count; i++) { + int remove = grpc_fd_is_orphaned(h->fds[i]); + for (nd = 0; nd < h->del_count; nd++) { + if (h->fds[i] == h->dels[nd]) remove = 1; + } + if (remove) { + grpc_fd_unref(h->fds[i]); + } else { + h->fds[nf++] = h->fds[i]; + h->pfds[np].events = + grpc_fd_begin_poll(h->fds[i], pollset, POLLIN, POLLOUT); + h->selfds[np] = h->fds[i]; + h->pfds[np].fd = h->fds[i]->fd; + h->pfds[np].revents = 0; + np++; + } + } + h->pfd_count = np; + h->fd_count = nf; + for (nd = 0; nd < h->del_count; nd++) { + grpc_fd_unref(h->dels[nd]); + } + h->del_count = 0; + if (h->pfd_count == 0) { + end_polling(pollset); + return 0; + } + pollset->counter = 1; + gpr_mu_unlock(&pollset->mu); + + r = poll(h->pfds, h->pfd_count, timeout); + if (r < 0) { + gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); + } else if (r == 0) { + /* do nothing */ + } else { + if (h->pfds[0].revents & POLLIN) { + grpc_kick_drain(pollset); + } + for (i = 1; i < np; i++) { + if (h->pfds[i].revents & POLLIN) { + grpc_fd_become_readable(h->selfds[i], allow_synchronous_callback); + } + if (h->pfds[i].revents & POLLOUT) { + grpc_fd_become_writable(h->selfds[i], allow_synchronous_callback); + } + } + } + end_polling(pollset); + + gpr_mu_lock(&pollset->mu); + pollset->counter = 0; + gpr_cv_broadcast(&pollset->cv); + return 1; +} + +static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) { + size_t i; + pollset_hdr *h = pollset->data.ptr; + GPR_ASSERT(pollset->counter == 0); + for (i = 0; i < h->fd_count; i++) { + grpc_fd_unref(h->fds[i]); + } + for (i = 0; i < h->del_count; i++) { + grpc_fd_unref(h->dels[i]); + } + gpr_free(h->pfds); + gpr_free(h->selfds); + gpr_free(h->fds); + gpr_free(h->dels); + gpr_free(h); +} + +static const grpc_pollset_vtable multipoll_with_poll_pollset = { + multipoll_with_poll_pollset_add_fd, multipoll_with_poll_pollset_del_fd, + multipoll_with_poll_pollset_maybe_work, + multipoll_with_poll_pollset_destroy}; + +void grpc_platform_become_multipoller(grpc_pollset *pollset, grpc_fd **fds, + size_t nfds) { + size_t i; + pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr)); + pollset->vtable = &multipoll_with_poll_pollset; + pollset->data.ptr = h; + h->fd_count = nfds; + h->fd_capacity = nfds; + h->fds = gpr_malloc(nfds * sizeof(grpc_fd *)); + h->pfd_count = 0; + h->pfd_capacity = 0; + h->pfds = NULL; + h->selfds = NULL; + h->del_count = 0; + h->del_capacity = 0; + h->dels = NULL; + for (i = 0; i < nfds; i++) { + h->fds[i] = fds[i]; + grpc_fd_ref(fds[i]); + } +} + +#endif diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c new file mode 100644 index 00000000000..ba4031e11f4 --- /dev/null +++ b/src/core/iomgr/pollset_posix.c @@ -0,0 +1,340 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/iomgr/pollset_posix.h" + +#include +#include +#include +#include +#include + +#include "src/core/iomgr/alarm_internal.h" +#include "src/core/iomgr/fd_posix.h" +#include "src/core/iomgr/iomgr_internal.h" +#include "src/core/iomgr/socket_utils_posix.h" +#include +#include +#include +#include + +/* kick pipes: we keep a sharded set of pipes to allow breaking from poll. + Ideally this would be 1:1 with pollsets, but we'd like to avoid associating + full kernel objects with each pollset to keep them lightweight, so instead + keep a sharded set and allow associating a pollset with one of the shards. + + TODO(ctiller): move this out from this file, and allow an eventfd + implementation on linux */ + +#define LOG2_KICK_SHARDS 6 +#define KICK_SHARDS (1 << LOG2_KICK_SHARDS) + +static int g_kick_pipes[KICK_SHARDS][2]; +static grpc_pollset g_backup_pollset; +static int g_shutdown_backup_poller; +static gpr_event g_backup_poller_done; + +static void backup_poller(void *p) { + gpr_timespec delta = gpr_time_from_millis(100); + gpr_timespec last_poll = gpr_now(); + + gpr_mu_lock(&g_backup_pollset.mu); + while (g_shutdown_backup_poller == 0) { + gpr_timespec next_poll = gpr_time_add(last_poll, delta); + grpc_pollset_work(&g_backup_pollset, next_poll); + gpr_mu_unlock(&g_backup_pollset.mu); + gpr_sleep_until(next_poll); + gpr_mu_lock(&g_backup_pollset.mu); + last_poll = next_poll; + } + gpr_mu_unlock(&g_backup_pollset.mu); + + gpr_event_set(&g_backup_poller_done, (void *)1); +} + +static size_t kick_shard(const grpc_pollset *info) { + size_t x = (size_t)info; + return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (KICK_SHARDS - 1); +} + +int grpc_kick_read_fd(grpc_pollset *p) { + return g_kick_pipes[kick_shard(p)][0]; +} + +static int grpc_kick_write_fd(grpc_pollset *p) { + return g_kick_pipes[kick_shard(p)][1]; +} + +void grpc_pollset_force_kick(grpc_pollset *p) { + char c = 0; + while (write(grpc_kick_write_fd(p), &c, 1) != 1 && errno == EINTR) + ; +} + +void grpc_pollset_kick(grpc_pollset *p) { + if (!p->counter) return; + grpc_pollset_force_kick(p); +} + +void grpc_kick_drain(grpc_pollset *p) { + int fd = grpc_kick_read_fd(p); + char buf[128]; + int r; + + for (;;) { + r = read(fd, buf, sizeof(buf)); + if (r > 0) continue; + if (r == 0) return; + switch (errno) { + case EAGAIN: + return; + case EINTR: + continue; + default: + gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno)); + return; + } + } +} + +/* global state management */ + +grpc_pollset *grpc_backup_pollset() { return &g_backup_pollset; } + +void grpc_pollset_global_init() { + int i; + gpr_thd_id id; + + /* initialize the kick shards */ + for (i = 0; i < KICK_SHARDS; i++) { + GPR_ASSERT(0 == pipe(g_kick_pipes[i])); + GPR_ASSERT(grpc_set_socket_nonblocking(g_kick_pipes[i][0], 1)); + GPR_ASSERT(grpc_set_socket_nonblocking(g_kick_pipes[i][1], 1)); + } + + /* initialize the backup pollset */ + grpc_pollset_init(&g_backup_pollset); + + /* start the backup poller thread */ + g_shutdown_backup_poller = 0; + gpr_event_init(&g_backup_poller_done); + gpr_thd_new(&id, backup_poller, NULL, NULL); +} + +void grpc_pollset_global_shutdown() { + int i; + + /* terminate the backup poller thread */ + gpr_mu_lock(&g_backup_pollset.mu); + g_shutdown_backup_poller = 1; + gpr_mu_unlock(&g_backup_pollset.mu); + gpr_event_wait(&g_backup_poller_done, gpr_inf_future); + + /* destroy the backup pollset */ + grpc_pollset_destroy(&g_backup_pollset); + + /* destroy the kick shards */ + for (i = 0; i < KICK_SHARDS; i++) { + close(g_kick_pipes[i][0]); + close(g_kick_pipes[i][1]); + } +} + +/* main interface */ + +static void become_empty_pollset(grpc_pollset *pollset); +static void become_unary_pollset(grpc_pollset *pollset, grpc_fd *fd); + +void grpc_pollset_init(grpc_pollset *pollset) { + gpr_mu_init(&pollset->mu); + gpr_cv_init(&pollset->cv); + become_empty_pollset(pollset); +} + +void grpc_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { + gpr_mu_lock(&pollset->mu); + pollset->vtable->add_fd(pollset, fd); + gpr_cv_broadcast(&pollset->cv); + gpr_mu_unlock(&pollset->mu); +} + +void grpc_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) { + gpr_mu_lock(&pollset->mu); + pollset->vtable->del_fd(pollset, fd); + gpr_cv_broadcast(&pollset->cv); + gpr_mu_unlock(&pollset->mu); +} + +int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { + /* pollset->mu already held */ + gpr_timespec now; + now = gpr_now(); + if (gpr_time_cmp(now, deadline) > 0) { + return 0; + } + if (grpc_maybe_call_delayed_callbacks(&pollset->mu, 1)) { + return 1; + } + if (grpc_alarm_check(&pollset->mu, now, &deadline)) { + return 1; + } + return pollset->vtable->maybe_work(pollset, deadline, now, 1); +} + +void grpc_pollset_destroy(grpc_pollset *pollset) { + pollset->vtable->destroy(pollset); + gpr_mu_destroy(&pollset->mu); + gpr_cv_destroy(&pollset->cv); +} + +/* + * empty_pollset - a vtable that provides polling for NO file descriptors + */ + +static void empty_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { + become_unary_pollset(pollset, fd); +} + +static void empty_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) {} + +static int empty_pollset_maybe_work(grpc_pollset *pollset, + gpr_timespec deadline, gpr_timespec now, + int allow_synchronous_callback) { + return 0; +} + +static void empty_pollset_destroy(grpc_pollset *pollset) {} + +static const grpc_pollset_vtable empty_pollset = { + empty_pollset_add_fd, empty_pollset_del_fd, empty_pollset_maybe_work, + empty_pollset_destroy}; + +static void become_empty_pollset(grpc_pollset *pollset) { + pollset->vtable = &empty_pollset; +} + +/* + * unary_poll_pollset - a vtable that provides polling for one file descriptor + * via poll() + */ + +static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { + grpc_fd *fds[2]; + if (fd == pollset->data.ptr) return; + fds[0] = pollset->data.ptr; + fds[1] = fd; + grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); + grpc_fd_unref(fds[0]); +} + +static void unary_poll_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) { + if (fd == pollset->data.ptr) { + grpc_fd_unref(pollset->data.ptr); + become_empty_pollset(pollset); + } +} + +static int unary_poll_pollset_maybe_work(grpc_pollset *pollset, + gpr_timespec deadline, + gpr_timespec now, + int allow_synchronous_callback) { + struct pollfd pfd[2]; + grpc_fd *fd; + int timeout; + int r; + + if (pollset->counter) { + return 0; + } + fd = pollset->data.ptr; + if (grpc_fd_is_orphaned(fd)) { + grpc_fd_unref(fd); + become_empty_pollset(pollset); + return 0; + } + if (gpr_time_cmp(deadline, gpr_inf_future) == 0) { + timeout = -1; + } else { + timeout = gpr_time_to_millis(gpr_time_sub(deadline, now)); + if (timeout <= 0) { + return 1; + } + } + pfd[0].fd = grpc_kick_read_fd(pollset); + pfd[0].events = POLLIN; + pfd[0].revents = 0; + pfd[1].fd = fd->fd; + pfd[1].events = grpc_fd_begin_poll(fd, pollset, POLLIN, POLLOUT); + pfd[1].revents = 0; + pollset->counter = 1; + gpr_mu_unlock(&pollset->mu); + + r = poll(pfd, GPR_ARRAY_SIZE(pfd), timeout); + if (r < 0) { + gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); + } else if (r == 0) { + /* do nothing */ + } else { + if (pfd[0].revents & POLLIN) { + grpc_kick_drain(pollset); + } + if (pfd[1].revents & POLLIN) { + grpc_fd_become_readable(fd, allow_synchronous_callback); + } + if (pfd[1].revents & POLLOUT) { + grpc_fd_become_writable(fd, allow_synchronous_callback); + } + } + + gpr_mu_lock(&pollset->mu); + grpc_fd_end_poll(fd, pollset); + pollset->counter = 0; + gpr_cv_broadcast(&pollset->cv); + return 1; +} + +static void unary_poll_pollset_destroy(grpc_pollset *pollset) { + GPR_ASSERT(pollset->counter == 0); + grpc_fd_unref(pollset->data.ptr); +} + +static const grpc_pollset_vtable unary_poll_pollset = { + unary_poll_pollset_add_fd, unary_poll_pollset_del_fd, + unary_poll_pollset_maybe_work, unary_poll_pollset_destroy}; + +static void become_unary_pollset(grpc_pollset *pollset, grpc_fd *fd) { + pollset->vtable = &unary_poll_pollset; + pollset->counter = 0; + pollset->data.ptr = fd; + grpc_fd_ref(fd); +} diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h new file mode 100644 index 00000000000..f051079f5b5 --- /dev/null +++ b/src/core/iomgr/pollset_posix.h @@ -0,0 +1,95 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_POSIX_H_ +#define __GRPC_INTERNAL_IOMGR_POLLSET_POSIX_H_ + +#include + +typedef struct grpc_pollset_vtable grpc_pollset_vtable; + +/* forward declare only in this file to avoid leaking impl details via + pollset.h; real users of grpc_fd should always include 'fd_posix.h' and not + use the struct tag */ +struct grpc_fd; + +typedef struct grpc_pollset { + /* pollsets under posix can mutate representation as fds are added and + removed. + For example, we may choose a poll() based implementation on linux for + few fds, and an epoll() based implementation for many fds */ + const grpc_pollset_vtable *vtable; + gpr_mu mu; + gpr_cv cv; + int counter; + union { + int fd; + void *ptr; + } data; +} grpc_pollset; + +struct grpc_pollset_vtable { + void (*add_fd)(grpc_pollset *pollset, struct grpc_fd *fd); + void (*del_fd)(grpc_pollset *pollset, struct grpc_fd *fd); + int (*maybe_work)(grpc_pollset *pollset, gpr_timespec deadline, + gpr_timespec now, int allow_synchronous_callback); + void (*destroy)(grpc_pollset *pollset); +}; + +#define GRPC_POLLSET_MU(pollset) (&(pollset)->mu) +#define GRPC_POLLSET_CV(pollset) (&(pollset)->cv) + +/* Add an fd to a pollset */ +void grpc_pollset_add_fd(grpc_pollset *pollset, struct grpc_fd *fd); +/* Force remove an fd from a pollset (normally they are removed on the next + poll after an fd is orphaned) */ +void grpc_pollset_del_fd(grpc_pollset *pollset, struct grpc_fd *fd); + +/* Force any current pollers to break polling */ +void grpc_pollset_force_kick(grpc_pollset *pollset); +/* Returns the fd to listen on for kicks */ +int grpc_kick_read_fd(grpc_pollset *p); +/* Call after polling has been kicked to leave the kicked state */ +void grpc_kick_drain(grpc_pollset *p); + +/* All fds get added to a backup pollset to ensure that progress is made + regardless of applications listening to events. Relying on this is slow + however (the backup pollset only listens every 100ms or so) - so it's not + to be relied on. */ +grpc_pollset *grpc_backup_pollset(); + +/* turn a pollset into a multipoller: platform specific */ +void grpc_platform_become_multipoller(grpc_pollset *pollset, + struct grpc_fd **fds, size_t fd_count); + +#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_POSIX_H_ */ diff --git a/src/core/iomgr/resolve_address_posix.c b/src/core/iomgr/resolve_address_posix.c index a0a04297eb1..c9c2c5378a5 100644 --- a/src/core/iomgr/resolve_address_posix.c +++ b/src/core/iomgr/resolve_address_posix.c @@ -41,7 +41,7 @@ #include #include -#include "src/core/iomgr/iomgr_libevent.h" +#include "src/core/iomgr/iomgr_internal.h" #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include @@ -201,7 +201,7 @@ static void do_request(void *rp) { gpr_free(r->default_port); gpr_free(r); cb(arg, resolved); - grpc_iomgr_ref_address_resolution(-1); + grpc_iomgr_unref(); } void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { @@ -213,7 +213,7 @@ void grpc_resolve_address(const char *name, const char *default_port, grpc_resolve_cb cb, void *arg) { request *r = gpr_malloc(sizeof(request)); gpr_thd_id id; - grpc_iomgr_ref_address_resolution(1); + grpc_iomgr_ref(); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->cb = cb; diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c index 88b599b582e..d675c2dcece 100644 --- a/src/core/iomgr/tcp_client_posix.c +++ b/src/core/iomgr/tcp_client_posix.c @@ -38,7 +38,9 @@ #include #include -#include "src/core/iomgr/iomgr_libevent.h" +#include "src/core/iomgr/alarm.h" +#include "src/core/iomgr/iomgr_posix.h" +#include "src/core/iomgr/pollset_posix.h" #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include "src/core/iomgr/tcp_posix.h" @@ -49,8 +51,11 @@ typedef struct { void (*cb)(void *arg, grpc_endpoint *tcp); void *cb_arg; + gpr_mu mu; grpc_fd *fd; gpr_timespec deadline; + grpc_alarm alarm; + int refs; } async_connect; static int prepare_socket(int fd) { @@ -74,21 +79,42 @@ error: return 0; } -static void on_writable(void *acp, grpc_iomgr_cb_status status) { +static void on_alarm(void *acp, int success) { + int done; + async_connect *ac = acp; + gpr_mu_lock(&ac->mu); + if (ac->fd != NULL && success) { + grpc_fd_shutdown(ac->fd); + } + done = (--ac->refs == 0); + gpr_mu_unlock(&ac->mu); + if (done) { + gpr_mu_destroy(&ac->mu); + gpr_free(ac); + } +} + +static void on_writable(void *acp, int success) { async_connect *ac = acp; int so_error = 0; socklen_t so_error_size; int err; - int fd = grpc_fd_get(ac->fd); + int fd = ac->fd->fd; + int done; + grpc_endpoint *ep = NULL; + void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb; + void *cb_arg = ac->cb_arg; + + grpc_alarm_cancel(&ac->alarm); - if (status == GRPC_CALLBACK_SUCCESS) { + if (success) { do { so_error_size = sizeof(so_error); err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size); } while (err < 0 && errno == EINTR); if (err < 0) { gpr_log(GPR_ERROR, "getsockopt(ERROR): %s", strerror(errno)); - goto error; + goto finish; } else if (so_error != 0) { if (so_error == ENOBUFS) { /* We will get one of these errors if we have run out of @@ -106,7 +132,7 @@ static void on_writable(void *acp, grpc_iomgr_cb_status status) { opened too many network connections. The "easy" fix: don't do that! */ gpr_log(GPR_ERROR, "kernel out of buffers"); - grpc_fd_notify_on_write(ac->fd, on_writable, ac, ac->deadline); + grpc_fd_notify_on_write(ac->fd, on_writable, ac); return; } else { switch (so_error) { @@ -117,27 +143,31 @@ static void on_writable(void *acp, grpc_iomgr_cb_status status) { gpr_log(GPR_ERROR, "socket error: %d", so_error); break; } - goto error; + goto finish; } } else { - goto great_success; + ep = grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE); + goto finish; } } else { - gpr_log(GPR_ERROR, "on_writable failed during connect: status=%d", status); - goto error; + gpr_log(GPR_ERROR, "on_writable failed during connect"); + goto finish; } abort(); -error: - ac->cb(ac->cb_arg, NULL); - grpc_fd_destroy(ac->fd, NULL, NULL); - gpr_free(ac); - return; - -great_success: - ac->cb(ac->cb_arg, grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); - gpr_free(ac); +finish: + gpr_mu_lock(&ac->mu); + if (!ep) { + grpc_fd_orphan(ac->fd, NULL, NULL); + } + done = (--ac->refs == 0); + gpr_mu_unlock(&ac->mu); + if (done) { + gpr_mu_destroy(&ac->mu); + gpr_free(ac); + } + cb(cb_arg, ep); } void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), @@ -176,6 +206,7 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), } while (err < 0 && errno == EINTR); if (err >= 0) { + gpr_log(GPR_DEBUG, "instant connect"); cb(arg, grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); return; @@ -191,7 +222,10 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), ac = gpr_malloc(sizeof(async_connect)); ac->cb = cb; ac->cb_arg = arg; - ac->deadline = deadline; ac->fd = grpc_fd_create(fd); - grpc_fd_notify_on_write(ac->fd, on_writable, ac, deadline); + gpr_mu_init(&ac->mu); + ac->refs = 2; + + grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); + grpc_fd_notify_on_write(ac->fd, on_writable, ac); } diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index bc3ce69e471..657f34aaf99 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -255,18 +255,14 @@ typedef struct { grpc_endpoint_read_cb read_cb; void *read_user_data; - gpr_timespec read_deadline; grpc_endpoint_write_cb write_cb; void *write_user_data; - gpr_timespec write_deadline; grpc_tcp_slice_state write_state; } grpc_tcp; -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, - grpc_iomgr_cb_status status); -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, - grpc_iomgr_cb_status status); +static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); +static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success); static void grpc_tcp_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; @@ -276,7 +272,7 @@ static void grpc_tcp_shutdown(grpc_endpoint *ep) { static void grpc_tcp_unref(grpc_tcp *tcp) { int refcount_zero = gpr_unref(&tcp->refcount); if (refcount_zero) { - grpc_fd_destroy(tcp->em_fd, NULL, NULL); + grpc_fd_orphan(tcp->em_fd, NULL, NULL); gpr_free(tcp); } } @@ -308,8 +304,7 @@ static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices, #define INLINE_SLICE_BUFFER_SIZE 8 #define MAX_READ_IOVEC 4 -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, - grpc_iomgr_cb_status status) { +static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; int iov_size = 1; gpr_slice static_read_slices[INLINE_SLICE_BUFFER_SIZE]; @@ -324,18 +319,12 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, slice_state_init(&read_state, static_read_slices, INLINE_SLICE_BUFFER_SIZE, 0); - if (status == GRPC_CALLBACK_CANCELLED) { + if (!success) { call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); grpc_tcp_unref(tcp); return; } - if (status == GRPC_CALLBACK_TIMED_OUT) { - call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_TIMED_OUT); - grpc_tcp_unref(tcp); - return; - } - /* TODO(klempner): Limit the amount we read at once. */ for (;;) { allocated_bytes = slice_state_append_blocks_into_iovec( @@ -377,8 +366,7 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, } else { /* Spurious read event, consume it here */ slice_state_destroy(&read_state); - grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp, - tcp->read_deadline); + grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp); } } else { /* TODO(klempner): Log interesting errors */ @@ -407,14 +395,13 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, } static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data, gpr_timespec deadline) { + void *user_data) { grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(tcp->read_cb == NULL); tcp->read_cb = cb; tcp->read_user_data = user_data; - tcp->read_deadline = deadline; gpr_ref(&tcp->refcount); - grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp, deadline); + grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp); } #define MAX_WRITE_IOVEC 16 @@ -460,34 +447,24 @@ static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { }; } -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, - grpc_iomgr_cb_status status) { +static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; grpc_endpoint_write_status write_status; grpc_endpoint_cb_status cb_status; grpc_endpoint_write_cb cb; - cb_status = GRPC_ENDPOINT_CB_OK; - - if (status == GRPC_CALLBACK_CANCELLED) { - cb_status = GRPC_ENDPOINT_CB_SHUTDOWN; - } else if (status == GRPC_CALLBACK_TIMED_OUT) { - cb_status = GRPC_ENDPOINT_CB_TIMED_OUT; - } - - if (cb_status != GRPC_ENDPOINT_CB_OK) { + if (!success) { slice_state_destroy(&tcp->write_state); cb = tcp->write_cb; tcp->write_cb = NULL; - cb(tcp->write_user_data, cb_status); + cb(tcp->write_user_data, GRPC_ENDPOINT_CB_SHUTDOWN); grpc_tcp_unref(tcp); return; } write_status = grpc_tcp_flush(tcp); if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { - grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp, - tcp->write_deadline); + grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp); } else { slice_state_destroy(&tcp->write_state); if (write_status == GRPC_ENDPOINT_WRITE_DONE) { @@ -502,9 +479,11 @@ static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, } } -static grpc_endpoint_write_status grpc_tcp_write( - grpc_endpoint *ep, gpr_slice *slices, size_t nslices, - grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline) { +static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_endpoint_write_status status; @@ -530,17 +509,15 @@ static grpc_endpoint_write_status grpc_tcp_write( gpr_ref(&tcp->refcount); tcp->write_cb = cb; tcp->write_user_data = user_data; - tcp->write_deadline = deadline; - grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp, - tcp->write_deadline); + grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp); } return status; } static void grpc_tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { - /* tickle the pollset so we crash if things aren't wired correctly */ - pollset->unused++; + grpc_tcp *tcp = (grpc_tcp *)ep; + grpc_pollset_add_fd(pollset, tcp->em_fd); } static const grpc_endpoint_vtable vtable = { @@ -550,14 +527,12 @@ static const grpc_endpoint_vtable vtable = { grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); tcp->base.vtable = &vtable; - tcp->fd = grpc_fd_get(em_fd); + tcp->fd = em_fd->fd; tcp->read_cb = NULL; tcp->write_cb = NULL; tcp->read_user_data = NULL; tcp->write_user_data = NULL; tcp->slice_size = slice_size; - tcp->read_deadline = gpr_inf_future; - tcp->write_deadline = gpr_inf_future; slice_state_init(&tcp->write_state, NULL, 0, 0); /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); diff --git a/src/core/iomgr/tcp_posix.h b/src/core/iomgr/tcp_posix.h index 830394d5344..c3eef1b4b73 100644 --- a/src/core/iomgr/tcp_posix.h +++ b/src/core/iomgr/tcp_posix.h @@ -45,7 +45,7 @@ */ #include "src/core/iomgr/endpoint.h" -#include "src/core/iomgr/iomgr_libevent.h" +#include "src/core/iomgr/fd_posix.h" #define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192 diff --git a/src/core/iomgr/tcp_server.h b/src/core/iomgr/tcp_server.h index 46fba13f901..1968246b751 100644 --- a/src/core/iomgr/tcp_server.h +++ b/src/core/iomgr/tcp_server.h @@ -49,8 +49,8 @@ typedef void (*grpc_tcp_server_cb)(void *arg, grpc_endpoint *ep); grpc_tcp_server *grpc_tcp_server_create(); /* Start listening to bound ports */ -void grpc_tcp_server_start(grpc_tcp_server *server, grpc_tcp_server_cb cb, - void *cb_arg); +void grpc_tcp_server_start(grpc_tcp_server *server, grpc_pollset *pollset, + grpc_tcp_server_cb cb, void *cb_arg); /* Add a port to the server, returning true on success, or false otherwise. diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c index 2abaf15ce4d..5ed517748a3 100644 --- a/src/core/iomgr/tcp_server_posix.c +++ b/src/core/iomgr/tcp_server_posix.c @@ -45,7 +45,7 @@ #include #include -#include "src/core/iomgr/iomgr_libevent.h" +#include "src/core/iomgr/pollset_posix.h" #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include "src/core/iomgr/tcp_posix.h" @@ -97,13 +97,8 @@ grpc_tcp_server *grpc_tcp_server_create() { return s; } -static void done_destroy(void *p, grpc_iomgr_cb_status status) { - gpr_event_set(p, (void *)1); -} - void grpc_tcp_server_destroy(grpc_tcp_server *s) { size_t i; - gpr_event fd_done; gpr_mu_lock(&s->mu); /* shutdown all fd's */ for (i = 0; i < s->nports; i++) { @@ -118,9 +113,7 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s) { /* delete ALL the things */ for (i = 0; i < s->nports; i++) { server_port *sp = &s->ports[i]; - gpr_event_init(&fd_done); - grpc_fd_destroy(sp->emfd, done_destroy, &fd_done); - gpr_event_wait(&fd_done, gpr_inf_future); + grpc_fd_orphan(sp->emfd, NULL, NULL); } gpr_free(s->ports); gpr_free(s); @@ -196,10 +189,10 @@ error: } /* event manager callback when reads are ready */ -static void on_read(void *arg, grpc_iomgr_cb_status status) { +static void on_read(void *arg, int success) { server_port *sp = arg; - if (status != GRPC_CALLBACK_SUCCESS) { + if (!success) { goto error; } @@ -215,7 +208,7 @@ static void on_read(void *arg, grpc_iomgr_cb_status status) { case EINTR: continue; case EAGAIN: - grpc_fd_notify_on_read(sp->emfd, on_read, sp, gpr_inf_future); + grpc_fd_notify_on_read(sp->emfd, on_read, sp); return; default: gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); @@ -254,15 +247,10 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd, s->ports = gpr_realloc(s->ports, sizeof(server_port *) * s->port_capacity); } sp = &s->ports[s->nports++]; - sp->emfd = grpc_fd_create(fd); - sp->fd = fd; sp->server = s; - /* initialize the em desc */ - if (sp->emfd == NULL) { - s->nports--; - gpr_mu_unlock(&s->mu); - return 0; - } + sp->fd = fd; + sp->emfd = grpc_fd_create(fd); + GPR_ASSERT(sp->emfd); gpr_mu_unlock(&s->mu); return 1; @@ -319,8 +307,8 @@ int grpc_tcp_server_get_fd(grpc_tcp_server *s, int index) { return (0 <= index && index < s->nports) ? s->ports[index].fd : -1; } -void grpc_tcp_server_start(grpc_tcp_server *s, grpc_tcp_server_cb cb, - void *cb_arg) { +void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset *pollset, + grpc_tcp_server_cb cb, void *cb_arg) { size_t i; GPR_ASSERT(cb); gpr_mu_lock(&s->mu); @@ -329,8 +317,10 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_tcp_server_cb cb, s->cb = cb; s->cb_arg = cb_arg; for (i = 0; i < s->nports; i++) { - grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i], - gpr_inf_future); + if (pollset) { + grpc_pollset_add_fd(pollset, s->ports[i].emfd); + } + grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i]); s->active_ports++; } gpr_mu_unlock(&s->mu); diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 442d2fa6249..c99ac8021d9 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -555,12 +555,11 @@ static int fake_oauth2_has_request_metadata_only( return 1; } -void on_simulated_token_fetch_done(void *user_data, - grpc_iomgr_cb_status status) { +void on_simulated_token_fetch_done(void *user_data, int success) { grpc_credentials_metadata_request *r = (grpc_credentials_metadata_request *)user_data; grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)r->creds; - GPR_ASSERT(status == GRPC_CALLBACK_SUCCESS); + GPR_ASSERT(success); r->cb(r->user_data, &c->access_token_md, 1, GRPC_CREDENTIALS_OK); grpc_credentials_metadata_request_destroy(r); } diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c index cab09ca49d3..7f0fdf73c97 100644 --- a/src/core/security/secure_endpoint.c +++ b/src/core/security/secure_endpoint.c @@ -184,8 +184,7 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, } static void endpoint_notify_on_read(grpc_endpoint *secure_ep, - grpc_endpoint_read_cb cb, void *user_data, - gpr_timespec deadline) { + grpc_endpoint_read_cb cb, void *user_data) { secure_endpoint *ep = (secure_endpoint *)secure_ep; ep->read_cb = cb; ep->read_user_data = user_data; @@ -200,7 +199,7 @@ static void endpoint_notify_on_read(grpc_endpoint *secure_ep, return; } - grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep, deadline); + grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep); } static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, @@ -217,9 +216,11 @@ static void on_write(void *data, grpc_endpoint_cb_status error) { secure_endpoint_unref(ep); } -static grpc_endpoint_write_status endpoint_write( - grpc_endpoint *secure_ep, gpr_slice *slices, size_t nslices, - grpc_endpoint_write_cb cb, void *user_data, gpr_timespec deadline) { +static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data) { int i = 0; int output_buffer_count = 0; tsi_result result = TSI_OK; @@ -308,7 +309,7 @@ static grpc_endpoint_write_status endpoint_write( /* Need to keep the endpoint alive across a transport */ secure_endpoint_ref(ep); status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices, - output_buffer_count, on_write, ep, deadline); + output_buffer_count, on_write, ep); if (status != GRPC_ENDPOINT_WRITE_PENDING) { secure_endpoint_unref(ep); } diff --git a/src/core/security/secure_transport_setup.c b/src/core/security/secure_transport_setup.c index eb112519121..3df91ed8e7f 100644 --- a/src/core/security/secure_transport_setup.c +++ b/src/core/security/secure_transport_setup.c @@ -105,6 +105,7 @@ static void check_peer(grpc_secure_transport_setup *s) { grpc_security_status peer_status; tsi_peer peer; tsi_result result = tsi_handshaker_extract_peer(s->handshaker, &peer); + if (result != TSI_OK) { gpr_log(GPR_ERROR, "Peer extraction failed with error %s", tsi_result_to_string(result)); @@ -152,9 +153,8 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { gpr_slice_from_copied_buffer((const char *)s->handshake_buffer, offset); /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - write_status = - grpc_endpoint_write(s->endpoint, &to_send, 1, - on_handshake_data_sent_to_peer, s, gpr_inf_future); + write_status = grpc_endpoint_write(s->endpoint, &to_send, 1, + on_handshake_data_sent_to_peer, s); if (write_status == GRPC_ENDPOINT_WRITE_ERROR) { gpr_log(GPR_ERROR, "Could not send handshake data to peer."); secure_transport_setup_done(s, 0); @@ -200,8 +200,7 @@ static void on_handshake_data_received_from_peer( /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ grpc_endpoint_notify_on_read(s->endpoint, - on_handshake_data_received_from_peer, setup, - gpr_inf_future); + on_handshake_data_received_from_peer, setup); cleanup_slices(slices, nslices); return; } else { @@ -258,8 +257,7 @@ static void on_handshake_data_sent_to_peer(void *setup, /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ grpc_endpoint_notify_on_read(s->endpoint, - on_handshake_data_received_from_peer, setup, - gpr_inf_future); + on_handshake_data_received_from_peer, setup); } else { check_peer(s); } diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index 28b56dd4c9d..9d7c0e5e5a8 100644 --- a/src/core/security/server_secure_chttp2.c +++ b/src/core/security/server_secure_chttp2.c @@ -77,9 +77,9 @@ static void on_accept(void *server, grpc_endpoint *tcp) { /* Note: the following code is the same with server_chttp2.c */ /* Server callback: start listening on our ports */ -static void start(grpc_server *server, void *tcpp) { +static void start(grpc_server *server, void *tcpp, grpc_pollset *pollset) { grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(tcp, on_accept, server); + grpc_tcp_server_start(tcp, pollset, on_accept, server); } /* Server callback: destroy the tcp listener (so we don't generate further diff --git a/src/core/support/time.c b/src/core/support/time.c index 712bdf441cf..5330092f56b 100644 --- a/src/core/support/time.c +++ b/src/core/support/time.c @@ -249,3 +249,18 @@ gpr_timespec gpr_timespec_from_timeval(struct timeval t) { ts.tv_nsec = t.tv_usec * 1000; return ts; } + +gpr_int32 gpr_time_to_millis(gpr_timespec t) { + if (t.tv_sec >= 2147483) { + if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) { + return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS; + } + return 2147483647; + } else if (t.tv_sec <= -2147483) { + /* TODO(ctiller): correct handling here (it's so far in the past do we + care?) */ + return -2147483648; + } else { + return t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS; + } +} diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 9ed617f665c..9c5f5064eba 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -878,9 +878,9 @@ grpc_metadata_buffer *grpc_call_get_metadata_buffer(grpc_call *call) { return &call->incoming_metadata; } -static void call_alarm(void *arg, grpc_iomgr_cb_status status) { +static void call_alarm(void *arg, int success) { grpc_call *call = arg; - if (status == GRPC_CALLBACK_SUCCESS) { + if (success) { grpc_call_cancel(call); } grpc_call_internal_unref(call); diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 4837f5b978e..b59c36e03a7 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -36,7 +36,7 @@ #include #include -#include "src/core/iomgr/iomgr_completion_queue_interface.h" +#include "src/core/iomgr/pollset.h" #include "src/core/surface/call.h" #include "src/core/surface/event_string.h" #include "src/core/surface/surface_trace.h" @@ -61,6 +61,7 @@ typedef struct event { /* Completion queue structure */ struct grpc_completion_queue { + /* TODO(ctiller): see if this can be removed */ int allow_polling; /* When refs drops to zero, we are in shutdown mode, and will be destroyable @@ -100,7 +101,7 @@ void grpc_completion_queue_dont_poll_test_only(grpc_completion_queue *cc) { /* Create and append an event to the queue. Returns the event so that its data members can be filled in. - Requires grpc_iomgr_mu locked. */ + Requires GRPC_POLLSET_MU(&cc->pollset) locked. */ static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type, void *tag, grpc_call *call, grpc_event_finish_func on_finish, void *user_data) { @@ -126,7 +127,8 @@ static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type, ev->bucket_prev = cc->buckets[bucket]->bucket_prev; ev->bucket_next->bucket_prev = ev->bucket_prev->bucket_next = ev; } - gpr_cv_broadcast(&grpc_iomgr_cv); + gpr_cv_broadcast(GRPC_POLLSET_CV(&cc->pollset)); + grpc_pollset_kick(&cc->pollset); return ev; } @@ -149,7 +151,7 @@ static void end_op_locked(grpc_completion_queue *cc, if (gpr_unref(&cc->refs)) { GPR_ASSERT(!cc->shutdown); cc->shutdown = 1; - gpr_cv_broadcast(&grpc_iomgr_cv); + gpr_cv_broadcast(GRPC_POLLSET_CV(&cc->pollset)); } } @@ -157,11 +159,11 @@ void grpc_cq_end_read(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_event_finish_func on_finish, void *user_data, grpc_byte_buffer *read) { event *ev; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); ev = add_locked(cc, GRPC_READ, tag, call, on_finish, user_data); ev->base.data.read = read; end_op_locked(cc, GRPC_READ); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } void grpc_cq_end_invoke_accepted(grpc_completion_queue *cc, void *tag, @@ -169,11 +171,11 @@ void grpc_cq_end_invoke_accepted(grpc_completion_queue *cc, void *tag, grpc_event_finish_func on_finish, void *user_data, grpc_op_error error) { event *ev; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); ev = add_locked(cc, GRPC_INVOKE_ACCEPTED, tag, call, on_finish, user_data); ev->base.data.invoke_accepted = error; end_op_locked(cc, GRPC_INVOKE_ACCEPTED); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, @@ -181,11 +183,11 @@ void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, grpc_event_finish_func on_finish, void *user_data, grpc_op_error error) { event *ev; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); ev = add_locked(cc, GRPC_WRITE_ACCEPTED, tag, call, on_finish, user_data); ev->base.data.write_accepted = error; end_op_locked(cc, GRPC_WRITE_ACCEPTED); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } void grpc_cq_end_finish_accepted(grpc_completion_queue *cc, void *tag, @@ -193,11 +195,11 @@ void grpc_cq_end_finish_accepted(grpc_completion_queue *cc, void *tag, grpc_event_finish_func on_finish, void *user_data, grpc_op_error error) { event *ev; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); ev = add_locked(cc, GRPC_FINISH_ACCEPTED, tag, call, on_finish, user_data); ev->base.data.finish_accepted = error; end_op_locked(cc, GRPC_FINISH_ACCEPTED); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } void grpc_cq_end_client_metadata_read(grpc_completion_queue *cc, void *tag, @@ -206,13 +208,13 @@ void grpc_cq_end_client_metadata_read(grpc_completion_queue *cc, void *tag, void *user_data, size_t count, grpc_metadata *elements) { event *ev; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); ev = add_locked(cc, GRPC_CLIENT_METADATA_READ, tag, call, on_finish, user_data); ev->base.data.client_metadata_read.count = count; ev->base.data.client_metadata_read.elements = elements; end_op_locked(cc, GRPC_CLIENT_METADATA_READ); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } void grpc_cq_end_finished(grpc_completion_queue *cc, void *tag, grpc_call *call, @@ -221,14 +223,14 @@ void grpc_cq_end_finished(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_metadata *metadata_elements, size_t metadata_count) { event *ev; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); ev = add_locked(cc, GRPC_FINISHED, tag, call, on_finish, user_data); ev->base.data.finished.status = status; ev->base.data.finished.details = details; ev->base.data.finished.metadata_count = metadata_count; ev->base.data.finished.metadata_elements = metadata_elements; end_op_locked(cc, GRPC_FINISHED); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, @@ -237,7 +239,7 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, gpr_timespec deadline, size_t metadata_count, grpc_metadata *metadata_elements) { event *ev; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); ev = add_locked(cc, GRPC_SERVER_RPC_NEW, tag, call, on_finish, user_data); ev->base.data.server_rpc_new.method = method; ev->base.data.server_rpc_new.host = host; @@ -245,7 +247,7 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, ev->base.data.server_rpc_new.metadata_count = metadata_count; ev->base.data.server_rpc_new.metadata_elements = metadata_elements; end_op_locked(cc, GRPC_SERVER_RPC_NEW); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } /* Create a GRPC_QUEUE_SHUTDOWN event without queuing it anywhere */ @@ -262,7 +264,7 @@ grpc_event *grpc_completion_queue_next(grpc_completion_queue *cc, gpr_timespec deadline) { event *ev = NULL; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); for (;;) { if (cc->queue != NULL) { gpr_uintptr bucket; @@ -288,15 +290,16 @@ grpc_event *grpc_completion_queue_next(grpc_completion_queue *cc, ev = create_shutdown_event(); break; } - if (cc->allow_polling && grpc_iomgr_work(deadline)) { + if (cc->allow_polling && grpc_pollset_work(&cc->pollset, deadline)) { continue; } - if (gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, deadline)) { - gpr_mu_unlock(&grpc_iomgr_mu); + if (gpr_cv_wait(GRPC_POLLSET_CV(&cc->pollset), + GRPC_POLLSET_MU(&cc->pollset), deadline)) { + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); return NULL; } } - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ev->base); return &ev->base; } @@ -334,7 +337,7 @@ grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, gpr_timespec deadline) { event *ev = NULL; - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); for (;;) { if ((ev = pluck_event(cc, tag))) { break; @@ -343,15 +346,16 @@ grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, ev = create_shutdown_event(); break; } - if (cc->allow_polling && grpc_iomgr_work(deadline)) { + if (cc->allow_polling && grpc_pollset_work(&cc->pollset, deadline)) { continue; } - if (gpr_cv_wait(&grpc_iomgr_cv, &grpc_iomgr_mu, deadline)) { - gpr_mu_unlock(&grpc_iomgr_mu); + if (gpr_cv_wait(GRPC_POLLSET_CV(&cc->pollset), + GRPC_POLLSET_MU(&cc->pollset), deadline)) { + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); return NULL; } } - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ev->base); return &ev->base; } @@ -360,11 +364,11 @@ grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, to zero here, then enter shutdown mode and wake up any waiters */ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) { if (gpr_unref(&cc->refs)) { - gpr_mu_lock(&grpc_iomgr_mu); + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); GPR_ASSERT(!cc->shutdown); cc->shutdown = 1; - gpr_cv_broadcast(&grpc_iomgr_cv); - gpr_mu_unlock(&grpc_iomgr_mu); + gpr_cv_broadcast(GRPC_POLLSET_CV(&cc->pollset)); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 3829e7aa8f9..aa544a97f28 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -52,7 +52,7 @@ typedef enum { PENDING_START, ALL_CALLS, CALL_LIST_COUNT } call_list; typedef struct listener { void *arg; - void (*start)(grpc_server *server, void *arg); + void (*start)(grpc_server *server, void *arg, grpc_pollset *pollset); void (*destroy)(grpc_server *server, void *arg); struct listener *next; } listener; @@ -192,7 +192,7 @@ static void orphan_channel(channel_data *chand) { chand->next = chand->prev = chand; } -static void finish_destroy_channel(void *cd, grpc_iomgr_cb_status status) { +static void finish_destroy_channel(void *cd, int success) { channel_data *chand = cd; grpc_server *server = chand->server; /*gpr_log(GPR_INFO, "destroy channel %p", chand->channel);*/ @@ -247,7 +247,7 @@ static void start_new_rpc(grpc_call_element *elem) { gpr_mu_unlock(&server->mu); } -static void kill_zombie(void *elem, grpc_iomgr_cb_status status) { +static void kill_zombie(void *elem, int success) { grpc_call_destroy(grpc_call_from_top_element(elem)); } @@ -336,7 +336,7 @@ static void channel_op(grpc_channel_element *elem, } } -static void finish_shutdown_channel(void *cd, grpc_iomgr_cb_status status) { +static void finish_shutdown_channel(void *cd, int success) { channel_data *chand = cd; grpc_channel_op op; op.type = GRPC_CHANNEL_DISCONNECT; @@ -468,7 +468,7 @@ void grpc_server_start(grpc_server *server) { listener *l; for (l = server->listeners; l; l = l->next) { - l->start(server, l->arg); + l->start(server, l->arg, grpc_cq_pollset(server->cq)); } } @@ -596,7 +596,8 @@ void grpc_server_destroy(grpc_server *server) { } void grpc_server_add_listener(grpc_server *server, void *arg, - void (*start)(grpc_server *server, void *arg), + void (*start)(grpc_server *server, void *arg, + grpc_pollset *pollset), void (*destroy)(grpc_server *server, void *arg)) { listener *l = gpr_malloc(sizeof(listener)); l->arg = arg; diff --git a/src/core/surface/server.h b/src/core/surface/server.h index f0773ab9d57..61292ebe4e6 100644 --- a/src/core/surface/server.h +++ b/src/core/surface/server.h @@ -47,7 +47,8 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, /* Add a listener to the server: when the server starts, it will call start, and when it shuts down, it will call destroy */ void grpc_server_add_listener(grpc_server *server, void *listener, - void (*start)(grpc_server *server, void *arg), + void (*start)(grpc_server *server, void *arg, + grpc_pollset *pollset), void (*destroy)(grpc_server *server, void *arg)); /* Setup a transport - creates a channel stack, binds the transport to the diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c index a5fdd037740..a0961bd4493 100644 --- a/src/core/surface/server_chttp2.c +++ b/src/core/surface/server_chttp2.c @@ -59,9 +59,9 @@ static void new_transport(void *server, grpc_endpoint *tcp) { } /* Server callback: start listening on our ports */ -static void start(grpc_server *server, void *tcpp) { +static void start(grpc_server *server, void *tcpp, grpc_pollset *pollset) { grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(tcp, new_transport, server); + grpc_tcp_server_start(tcp, pollset, new_transport, server); } /* Server callback: destroy the tcp listener (so we don't generate further diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index a8ae8cc5bc0..5bf763e76f5 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -711,7 +711,7 @@ static void unlock(transport *t) { /* write some bytes if necessary */ while (start_write) { switch (grpc_endpoint_write(ep, t->outbuf.slices, t->outbuf.count, - finish_write, t, gpr_inf_future)) { + finish_write, t)) { case GRPC_ENDPOINT_WRITE_DONE: /* grab the lock directly without wrappers since we just want to continue writes if we loop: no need to check read callbacks again */ @@ -1617,7 +1617,6 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, case GRPC_ENDPOINT_CB_SHUTDOWN: case GRPC_ENDPOINT_CB_EOF: case GRPC_ENDPOINT_CB_ERROR: - case GRPC_ENDPOINT_CB_TIMED_OUT: lock(t); drop_connection(t); t->reading = 0; @@ -1642,7 +1641,7 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, for (i = 0; i < nslices; i++) gpr_slice_unref(slices[i]); if (keep_reading) { - grpc_endpoint_notify_on_read(t->ep, recv_data, t, gpr_inf_future); + grpc_endpoint_notify_on_read(t->ep, recv_data, t); } } diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c index 1181f1b4de9..e5b7304743f 100644 --- a/test/core/end2end/cq_verifier.c +++ b/test/core/end2end/cq_verifier.c @@ -371,7 +371,12 @@ void cq_verify_empty(cq_verifier *v) { GPR_ASSERT(v->expect.next == &v->expect && "expectation queue must be empty"); ev = grpc_completion_queue_next(v->cq, deadline); - GPR_ASSERT(ev == NULL); + if (ev != NULL) { + char *s = grpc_event_string(ev); + gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s", s); + gpr_free(s); + abort(); + } } static expectation *add(cq_verifier *v, grpc_completion_type type, void *tag) { diff --git a/test/core/end2end/fixtures/chttp2_socket_pair.c b/test/core/end2end/fixtures/chttp2_socket_pair.c index b3fac796f4c..cb5c6f7cad8 100644 --- a/test/core/end2end/fixtures/chttp2_socket_pair.c +++ b/test/core/end2end/fixtures/chttp2_socket_pair.c @@ -120,6 +120,7 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, GPR_ASSERT(!f->server); f->server = grpc_server_create_from_filters(f->server_cq, NULL, 0, server_args); + grpc_server_start(f->server); grpc_create_chttp2_transport(server_setup_transport, f, server_args, sfd->server, NULL, 0, grpc_mdctx_create(), 0); } diff --git a/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c b/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c index 061e049a09d..84acfa6d6cd 100644 --- a/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c +++ b/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c @@ -120,6 +120,7 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, GPR_ASSERT(!f->server); f->server = grpc_server_create_from_filters(f->server_cq, NULL, 0, server_args); + grpc_server_start(f->server); grpc_create_chttp2_transport(server_setup_transport, f, server_args, sfd->server, NULL, 0, grpc_mdctx_create(), 0); } diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c index d15fef6adc1..bad86fb9dcd 100644 --- a/test/core/end2end/tests/invoke_large_request.c +++ b/test/core/end2end/tests/invoke_large_request.c @@ -112,7 +112,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { gpr_slice request_payload_slice = large_slice(); grpc_byte_buffer *request_payload = grpc_byte_buffer_create(&request_payload_slice, 1); - gpr_timespec deadline = n_seconds_time(10); + gpr_timespec deadline = n_seconds_time(30); grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL); cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index 08198d49fbd..a418d1b15f3 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -156,9 +156,12 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { grpc_call *c2; grpc_call *s1; grpc_call *s2; + int live_call; + grpc_call *live_call_obj; gpr_timespec deadline; cq_verifier *v_client; cq_verifier *v_server; + grpc_event *ev; server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS; server_arg.type = GRPC_ARG_INTEGER; @@ -180,9 +183,10 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* start two requests - ensuring that the second is not accepted until the first completes */ deadline = five_seconds_time(); - c1 = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c1 = + grpc_channel_create_call(f.client, "/alpha", "test.google.com", deadline); GPR_ASSERT(c1); - c2 = grpc_channel_create_call(f.client, "/bar", "test.google.com", deadline); + c2 = grpc_channel_create_call(f.client, "/beta", "test.google.com", deadline); GPR_ASSERT(c1); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); @@ -191,19 +195,29 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { tag(301), tag(302), 0)); GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_invoke(c2, f.client_cq, tag(400), tag(401), tag(402), 0)); - cq_expect_invoke_accepted(v_client, tag(300), GRPC_OP_OK); - cq_verify(v_client); + ev = grpc_completion_queue_next( + f.client_cq, gpr_time_add(gpr_now(), gpr_time_from_seconds(10))); + GPR_ASSERT(ev); + GPR_ASSERT(ev->type == GRPC_INVOKE_ACCEPTED); + GPR_ASSERT(ev->data.invoke_accepted == GRPC_OP_OK); + /* The /alpha or /beta calls started above could be invoked (but NOT both); + * check this here */ + live_call = (int)(gpr_intptr)ev->tag; + live_call_obj = live_call == 300 ? c1 : c2; + grpc_event_finish(ev); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c1, tag(303))); - cq_expect_finish_accepted(v_client, tag(303), GRPC_OP_OK); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_writes_done(live_call_obj, tag(live_call + 3))); + cq_expect_finish_accepted(v_client, tag(live_call + 3), GRPC_OP_OK); cq_verify(v_client); - cq_expect_server_rpc_new(v_server, &s1, tag(100), "/foo", "test.google.com", - deadline, NULL); + cq_expect_server_rpc_new(v_server, &s1, tag(100), + live_call == 300 ? "/alpha" : "/beta", + "test.google.com", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == grpc_call_accept(s1, f.server_cq, tag(102), 0)); - cq_expect_client_metadata_read(v_client, tag(301), NULL); + cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == @@ -214,22 +228,26 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { cq_verify(v_server); /* first request is finished, we should be able to start the second */ - cq_expect_finished_with_status(v_client, tag(302), GRPC_STATUS_UNIMPLEMENTED, - "xyz", NULL); - cq_expect_invoke_accepted(v_client, tag(400), GRPC_OP_OK); + cq_expect_finished_with_status(v_client, tag(live_call + 2), + GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); + live_call = (live_call == 300) ? 400 : 300; + live_call_obj = live_call == 300 ? c1 : c2; + cq_expect_invoke_accepted(v_client, tag(live_call), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c2, tag(403))); - cq_expect_finish_accepted(v_client, tag(403), GRPC_OP_OK); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_writes_done(live_call_obj, tag(live_call + 3))); + cq_expect_finish_accepted(v_client, tag(live_call + 3), GRPC_OP_OK); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(200))); - cq_expect_server_rpc_new(v_server, &s2, tag(200), "/bar", "test.google.com", - deadline, NULL); + cq_expect_server_rpc_new(v_server, &s2, tag(200), + live_call == 300 ? "/alpha" : "/beta", + "test.google.com", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == grpc_call_accept(s2, f.server_cq, tag(202), 0)); - cq_expect_client_metadata_read(v_client, tag(401), NULL); + cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == @@ -239,8 +257,8 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { cq_expect_finished(v_server, tag(202), NULL); cq_verify(v_server); - cq_expect_finished_with_status(v_client, tag(402), GRPC_STATUS_UNIMPLEMENTED, - "xyz", NULL); + cq_expect_finished_with_status(v_client, tag(live_call + 2), + GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); cq_verify(v_client); cq_verifier_destroy(v_client); diff --git a/test/core/iomgr/alarm_list_test.c b/test/core/iomgr/alarm_list_test.c index a8aa6126e62..686d21d705a 100644 --- a/test/core/iomgr/alarm_list_test.c +++ b/test/core/iomgr/alarm_list_test.c @@ -41,13 +41,13 @@ #define MAX_CB 30 -static int cb_called[MAX_CB][GRPC_CALLBACK_DO_NOT_USE]; +static int cb_called[MAX_CB][2]; static int kicks; void grpc_kick_poller() { ++kicks; } -static void cb(void *arg, grpc_iomgr_cb_status status) { - cb_called[(gpr_intptr)arg][status]++; +static void cb(void *arg, int success) { + cb_called[(gpr_intptr)arg][success]++; } static void add_test() { @@ -72,36 +72,36 @@ static void add_test() { /* collect alarms. Only the first batch should be ready. */ GPR_ASSERT(10 == - grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(500)))); + grpc_alarm_check( + NULL, gpr_time_add(start, gpr_time_from_millis(500)), NULL)); for (i = 0; i < 20; i++) { - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 10)); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); + GPR_ASSERT(cb_called[i][1] == (i < 10)); + GPR_ASSERT(cb_called[i][0] == 0); } GPR_ASSERT(0 == - grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(600)))); + grpc_alarm_check( + NULL, gpr_time_add(start, gpr_time_from_millis(600)), NULL)); for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 10)); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); + GPR_ASSERT(cb_called[i][1] == (i < 10)); + GPR_ASSERT(cb_called[i][0] == 0); } /* collect the rest of the alarms */ GPR_ASSERT(10 == - grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(1500)))); + grpc_alarm_check( + NULL, gpr_time_add(start, gpr_time_from_millis(1500)), NULL)); for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 20)); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); + GPR_ASSERT(cb_called[i][1] == (i < 20)); + GPR_ASSERT(cb_called[i][0] == 0); } GPR_ASSERT(0 == - grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(1600)))); + grpc_alarm_check( + NULL, gpr_time_add(start, gpr_time_from_millis(1600)), NULL)); for (i = 0; i < 30; i++) { - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_SUCCESS] == (i < 20)); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_CANCELLED] == 0); - GPR_ASSERT(cb_called[i][GRPC_CALLBACK_TIMED_OUT] == 0); + GPR_ASSERT(cb_called[i][1] == (i < 20)); + GPR_ASSERT(cb_called[i][0] == 0); } grpc_alarm_list_shutdown(); @@ -124,16 +124,16 @@ void destruction_test() { (void *)(gpr_intptr)3, gpr_time_0); grpc_alarm_init(&alarms[4], gpr_time_from_millis(1), cb, (void *)(gpr_intptr)4, gpr_time_0); - GPR_ASSERT(1 == grpc_alarm_check(gpr_time_from_millis(2))); - GPR_ASSERT(1 == cb_called[4][GRPC_CALLBACK_SUCCESS]); + GPR_ASSERT(1 == grpc_alarm_check(NULL, gpr_time_from_millis(2), NULL)); + GPR_ASSERT(1 == cb_called[4][1]); grpc_alarm_cancel(&alarms[0]); grpc_alarm_cancel(&alarms[3]); - GPR_ASSERT(1 == cb_called[0][GRPC_CALLBACK_CANCELLED]); - GPR_ASSERT(1 == cb_called[3][GRPC_CALLBACK_CANCELLED]); + GPR_ASSERT(1 == cb_called[0][0]); + GPR_ASSERT(1 == cb_called[3][0]); grpc_alarm_list_shutdown(); - GPR_ASSERT(1 == cb_called[1][GRPC_CALLBACK_CANCELLED]); - GPR_ASSERT(1 == cb_called[2][GRPC_CALLBACK_CANCELLED]); + GPR_ASSERT(1 == cb_called[1][0]); + GPR_ASSERT(1 == cb_called[2][0]); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/alarm_test.c b/test/core/iomgr/alarm_test.c index 271c42d57e2..247320de04f 100644 --- a/test/core/iomgr/alarm_test.c +++ b/test/core/iomgr/alarm_test.c @@ -51,8 +51,10 @@ #include #include "test/core/util/test_config.h" +#define SUCCESS_NOT_SET (-1) + /* Dummy gRPC callback */ -void no_op_cb(void *arg, grpc_iomgr_cb_status status) {} +void no_op_cb(void *arg, int success) {} typedef struct { gpr_cv cv; @@ -62,27 +64,25 @@ typedef struct { int done_cancel_ctr; int done; gpr_event fcb_arg; - grpc_iomgr_cb_status status; + int success; } alarm_arg; -static void followup_cb(void *arg, grpc_iomgr_cb_status status) { +static void followup_cb(void *arg, int success) { gpr_event_set((gpr_event *)arg, arg); } /* Called when an alarm expires. */ -static void alarm_cb(void *arg /* alarm_arg */, grpc_iomgr_cb_status status) { +static void alarm_cb(void *arg /* alarm_arg */, int success) { alarm_arg *a = arg; gpr_mu_lock(&a->mu); - if (status == GRPC_CALLBACK_SUCCESS) { + if (success) { a->counter++; a->done_success_ctr++; - } else if (status == GRPC_CALLBACK_CANCELLED) { - a->done_cancel_ctr++; } else { - GPR_ASSERT(0); + a->done_cancel_ctr++; } a->done = 1; - a->status = status; + a->success = success; gpr_cv_signal(&a->cv); gpr_mu_unlock(&a->mu); grpc_iomgr_add_callback(followup_cb, &a->fcb_arg); @@ -105,7 +105,7 @@ static void test_grpc_alarm() { grpc_iomgr_init(); arg.counter = 0; - arg.status = GRPC_CALLBACK_DO_NOT_USE; + arg.success = SUCCESS_NOT_SET; arg.done_success_ctr = 0; arg.done_cancel_ctr = 0; arg.done = 0; @@ -138,7 +138,7 @@ static void test_grpc_alarm() { } else if (arg.done_cancel_ctr != 0) { gpr_log(GPR_ERROR, "Alarm done callback called with cancel"); GPR_ASSERT(0); - } else if (arg.status == GRPC_CALLBACK_DO_NOT_USE) { + } else if (arg.success == SUCCESS_NOT_SET) { gpr_log(GPR_ERROR, "Alarm callback without status"); GPR_ASSERT(0); } else { @@ -154,7 +154,7 @@ static void test_grpc_alarm() { gpr_mu_destroy(&arg.mu); arg2.counter = 0; - arg2.status = GRPC_CALLBACK_DO_NOT_USE; + arg2.success = SUCCESS_NOT_SET; arg2.done_success_ctr = 0; arg2.done_cancel_ctr = 0; arg2.done = 0; @@ -188,7 +188,7 @@ static void test_grpc_alarm() { } else if (arg2.done_cancel_ctr + arg2.done_success_ctr != 1) { gpr_log(GPR_ERROR, "Alarm done callback called incorrect number of times"); GPR_ASSERT(0); - } else if (arg2.status == GRPC_CALLBACK_DO_NOT_USE) { + } else if (arg2.success == SUCCESS_NOT_SET) { gpr_log(GPR_ERROR, "Alarm callback without status"); GPR_ASSERT(0); } else if (arg2.done_success_ctr) { diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c index 6a7f6afbc6b..125cde46785 100644 --- a/test/core/iomgr/endpoint_tests.c +++ b/test/core/iomgr/endpoint_tests.c @@ -145,8 +145,8 @@ static void read_and_write_test_read_handler(void *data, gpr_slice *slices, gpr_cv_signal(&state->cv); gpr_mu_unlock(&state->mu); } else { - grpc_endpoint_notify_on_read( - state->read_ep, read_and_write_test_read_handler, data, gpr_inf_future); + grpc_endpoint_notify_on_read(state->read_ep, + read_and_write_test_read_handler, data); } } @@ -159,6 +159,8 @@ static void read_and_write_test_write_handler(void *data, GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); + gpr_log(GPR_DEBUG, "%s: error=%d", __FUNCTION__, error); + if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { gpr_log(GPR_INFO, "Write handler shutdown"); gpr_mu_lock(&state->mu); @@ -182,9 +184,10 @@ static void read_and_write_test_write_handler(void *data, slices = allocate_blocks(state->current_write_size, 8192, &nslices, &state->current_write_data); - write_status = grpc_endpoint_write(state->write_ep, slices, nslices, - read_and_write_test_write_handler, state, - gpr_inf_future); + write_status = + grpc_endpoint_write(state->write_ep, slices, nslices, + read_and_write_test_write_handler, state); + gpr_log(GPR_DEBUG, "write_status=%d", write_status); GPR_ASSERT(write_status != GRPC_ENDPOINT_WRITE_ERROR); free(slices); if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { @@ -208,8 +211,7 @@ static void read_and_write_test(grpc_endpoint_test_config config, size_t num_bytes, size_t write_size, size_t slice_size, int shutdown) { struct read_and_write_test_state state; - gpr_timespec rel_deadline = {20, 0}; - gpr_timespec deadline = gpr_time_add(gpr_now(), rel_deadline); + gpr_timespec deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(20)); grpc_endpoint_test_fixture f = begin_test(config, __FUNCTION__, slice_size); if (shutdown) { @@ -241,16 +243,22 @@ static void read_and_write_test(grpc_endpoint_test_config config, read_and_write_test_write_handler(&state, GRPC_ENDPOINT_CB_OK); grpc_endpoint_notify_on_read(state.read_ep, read_and_write_test_read_handler, - &state, gpr_inf_future); + &state); if (shutdown) { + gpr_log(GPR_DEBUG, "shutdown read"); grpc_endpoint_shutdown(state.read_ep); + gpr_log(GPR_DEBUG, "shutdown write"); grpc_endpoint_shutdown(state.write_ep); } gpr_mu_lock(&state.mu); while (!state.read_done || !state.write_done) { - GPR_ASSERT(gpr_cv_wait(&state.cv, &state.mu, deadline) == 0); + if (gpr_cv_wait(&state.cv, &state.mu, deadline)) { + gpr_log(GPR_ERROR, "timeout: read_done=%d, write_done=%d", + state.read_done, state.write_done); + abort(); + } } gpr_mu_unlock(&state.mu); @@ -265,79 +273,6 @@ struct timeout_test_state { gpr_event io_done; }; -static void read_timeout_test_read_handler(void *data, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error) { - struct timeout_test_state *state = data; - GPR_ASSERT(error == GRPC_ENDPOINT_CB_TIMED_OUT); - gpr_event_set(&state->io_done, (void *)1); -} - -static void read_timeout_test(grpc_endpoint_test_config config, - size_t slice_size) { - gpr_timespec timeout = gpr_time_from_micros(10000); - gpr_timespec read_deadline = gpr_time_add(gpr_now(), timeout); - gpr_timespec test_deadline = - gpr_time_add(gpr_now(), gpr_time_from_micros(2000000)); - struct timeout_test_state state; - grpc_endpoint_test_fixture f = begin_test(config, __FUNCTION__, slice_size); - - gpr_event_init(&state.io_done); - - grpc_endpoint_notify_on_read(f.client_ep, read_timeout_test_read_handler, - &state, read_deadline); - GPR_ASSERT(gpr_event_wait(&state.io_done, test_deadline)); - grpc_endpoint_destroy(f.client_ep); - grpc_endpoint_destroy(f.server_ep); - end_test(config); -} - -static void write_timeout_test_write_handler(void *data, - grpc_endpoint_cb_status error) { - struct timeout_test_state *state = data; - GPR_ASSERT(error == GRPC_ENDPOINT_CB_TIMED_OUT); - gpr_event_set(&state->io_done, (void *)1); -} - -static void write_timeout_test(grpc_endpoint_test_config config, - size_t slice_size) { - gpr_timespec timeout = gpr_time_from_micros(10000); - gpr_timespec write_deadline = gpr_time_add(gpr_now(), timeout); - gpr_timespec test_deadline = - gpr_time_add(gpr_now(), gpr_time_from_micros(2000000)); - struct timeout_test_state state; - int current_data = 1; - gpr_slice *slices; - size_t nblocks; - size_t size; - grpc_endpoint_test_fixture f = begin_test(config, __FUNCTION__, slice_size); - - gpr_event_init(&state.io_done); - - /* TODO(klempner): Factor this out with the equivalent code in tcp_test.c */ - for (size = 1;; size *= 2) { - slices = allocate_blocks(size, 1, &nblocks, ¤t_data); - switch (grpc_endpoint_write(f.client_ep, slices, nblocks, - write_timeout_test_write_handler, &state, - write_deadline)) { - case GRPC_ENDPOINT_WRITE_DONE: - break; - case GRPC_ENDPOINT_WRITE_ERROR: - gpr_log(GPR_ERROR, "error writing"); - abort(); - case GRPC_ENDPOINT_WRITE_PENDING: - GPR_ASSERT(gpr_event_wait(&state.io_done, test_deadline)); - gpr_free(slices); - goto exit; - } - gpr_free(slices); - } -exit: - grpc_endpoint_destroy(f.client_ep); - grpc_endpoint_destroy(f.server_ep); - end_test(config); -} - typedef struct { gpr_event ev; grpc_endpoint *ep; @@ -357,9 +292,8 @@ static void shutdown_during_write_test_read_handler( grpc_endpoint_destroy(st->ep); gpr_event_set(&st->ev, (void *)(gpr_intptr)error); } else { - grpc_endpoint_notify_on_read(st->ep, - shutdown_during_write_test_read_handler, - user_data, gpr_inf_future); + grpc_endpoint_notify_on_read( + st->ep, shutdown_during_write_test_read_handler, user_data); } } @@ -397,14 +331,13 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, gpr_event_init(&read_st.ev); gpr_event_init(&write_st.ev); - grpc_endpoint_notify_on_read(read_st.ep, - shutdown_during_write_test_read_handler, - &read_st, gpr_inf_future); + grpc_endpoint_notify_on_read( + read_st.ep, shutdown_during_write_test_read_handler, &read_st); for (size = 1;; size *= 2) { slices = allocate_blocks(size, 1, &nblocks, ¤t_data); switch (grpc_endpoint_write(write_st.ep, slices, nblocks, shutdown_during_write_test_write_handler, - &write_st, gpr_inf_future)) { + &write_st)) { case GRPC_ENDPOINT_WRITE_DONE: break; case GRPC_ENDPOINT_WRITE_ERROR: @@ -432,7 +365,5 @@ void grpc_endpoint_tests(grpc_endpoint_test_config config) { read_and_write_test(config, 10000000, 100000, 8192, 0); read_and_write_test(config, 1000000, 100000, 1, 0); read_and_write_test(config, 100000000, 100000, 1, 1); - read_timeout_test(config, 1000); - write_timeout_test(config, 1000); shutdown_during_write_test(config, 1000); } diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c index c3a0afdb255..325c9f0221d 100644 --- a/test/core/iomgr/fd_posix_test.c +++ b/test/core/iomgr/fd_posix_test.c @@ -31,8 +31,7 @@ * */ -/* Test gRPC event manager with a simple TCP upload server and client. */ -#include "src/core/iomgr/iomgr_libevent.h" +#include "src/core/iomgr/fd_posix.h" #include #include @@ -85,7 +84,7 @@ static void create_test_socket(int port, int *socket_fd, } /* Dummy gRPC callback */ -void no_op_cb(void *arg, enum grpc_em_cb_status status) {} +void no_op_cb(void *arg, int success) {} /* =======An upload server to test notify_on_read=========== The server simply reads and counts a stream of bytes. */ @@ -117,10 +116,10 @@ typedef struct { /* Called when an upload session can be safely shutdown. Close session FD and start to shutdown listen FD. */ static void session_shutdown_cb(void *arg, /*session*/ - enum grpc_em_cb_status status) { + int success) { session *se = arg; server *sv = se->sv; - grpc_fd_destroy(se->em_fd, NULL, NULL); + grpc_fd_orphan(se->em_fd, NULL, NULL); gpr_free(se); /* Start to shutdown listen fd. */ grpc_fd_shutdown(sv->em_fd); @@ -128,15 +127,15 @@ static void session_shutdown_cb(void *arg, /*session*/ /* Called when data become readable in a session. */ static void session_read_cb(void *arg, /*session*/ - enum grpc_em_cb_status status) { + int success) { session *se = arg; - int fd = grpc_fd_get(se->em_fd); + int fd = se->em_fd->fd; ssize_t read_once = 0; ssize_t read_total = 0; - if (status == GRPC_CALLBACK_CANCELLED) { - session_shutdown_cb(arg, GRPC_CALLBACK_SUCCESS); + if (!success) { + session_shutdown_cb(arg, 1); return; } @@ -151,8 +150,7 @@ static void session_read_cb(void *arg, /*session*/ It is possible to read nothing due to spurious edge event or data has been drained, In such a case, read() returns -1 and set errno to EAGAIN. */ if (read_once == 0) { - grpc_fd_shutdown(se->em_fd); - grpc_fd_notify_on_read(se->em_fd, session_read_cb, se, gpr_inf_future); + session_shutdown_cb(arg, 1); } else if (read_once == -1) { if (errno == EAGAIN) { /* An edge triggered event is cached in the kernel until next poll. @@ -163,8 +161,7 @@ static void session_read_cb(void *arg, /*session*/ TODO(chenw): in multi-threaded version, callback and polling can be run in different threads. polling may catch a persist read edge event before notify_on_read is called. */ - GPR_ASSERT(grpc_fd_notify_on_read(se->em_fd, session_read_cb, se, - gpr_inf_future)); + grpc_fd_notify_on_read(se->em_fd, session_read_cb, se); } else { gpr_log(GPR_ERROR, "Unhandled read error %s", strerror(errno)); GPR_ASSERT(0); @@ -174,11 +171,10 @@ static void session_read_cb(void *arg, /*session*/ /* Called when the listen FD can be safely shutdown. Close listen FD and signal that server can be shutdown. */ -static void listen_shutdown_cb(void *arg /*server*/, - enum grpc_em_cb_status status) { +static void listen_shutdown_cb(void *arg /*server*/, int success) { server *sv = arg; - grpc_fd_destroy(sv->em_fd, NULL, NULL); + grpc_fd_orphan(sv->em_fd, NULL, NULL); gpr_mu_lock(&sv->mu); sv->done = 1; @@ -188,21 +184,21 @@ static void listen_shutdown_cb(void *arg /*server*/, /* Called when a new TCP connection request arrives in the listening port. */ static void listen_cb(void *arg, /*=sv_arg*/ - enum grpc_em_cb_status status) { + int success) { server *sv = arg; int fd; int flags; session *se; struct sockaddr_storage ss; socklen_t slen = sizeof(ss); - struct grpc_fd *listen_em_fd = sv->em_fd; + grpc_fd *listen_em_fd = sv->em_fd; - if (status == GRPC_CALLBACK_CANCELLED) { - listen_shutdown_cb(arg, GRPC_CALLBACK_SUCCESS); + if (!success) { + listen_shutdown_cb(arg, 1); return; } - fd = accept(grpc_fd_get(listen_em_fd), (struct sockaddr *)&ss, &slen); + fd = accept(listen_em_fd->fd, (struct sockaddr *)&ss, &slen); GPR_ASSERT(fd >= 0); GPR_ASSERT(fd < FD_SETSIZE); flags = fcntl(fd, F_GETFL, 0); @@ -210,11 +206,9 @@ static void listen_cb(void *arg, /*=sv_arg*/ se = gpr_malloc(sizeof(*se)); se->sv = sv; se->em_fd = grpc_fd_create(fd); - GPR_ASSERT( - grpc_fd_notify_on_read(se->em_fd, session_read_cb, se, gpr_inf_future)); + grpc_fd_notify_on_read(se->em_fd, session_read_cb, se); - GPR_ASSERT( - grpc_fd_notify_on_read(listen_em_fd, listen_cb, sv, gpr_inf_future)); + grpc_fd_notify_on_read(listen_em_fd, listen_cb, sv); } /* Max number of connections pending to be accepted by listen(). */ @@ -239,7 +233,7 @@ static int server_start(server *sv) { sv->em_fd = grpc_fd_create(fd); /* Register to be interested in reading from listen_fd. */ - GPR_ASSERT(grpc_fd_notify_on_read(sv->em_fd, listen_cb, sv, gpr_inf_future)); + grpc_fd_notify_on_read(sv->em_fd, listen_cb, sv); return port; } @@ -285,25 +279,24 @@ static void client_init(client *cl) { } /* Called when a client upload session is ready to shutdown. */ -static void client_session_shutdown_cb(void *arg /*client*/, - enum grpc_em_cb_status status) { +static void client_session_shutdown_cb(void *arg /*client*/, int success) { client *cl = arg; - grpc_fd_destroy(cl->em_fd, NULL, NULL); - gpr_mu_lock(&cl->mu); + grpc_fd_orphan(cl->em_fd, NULL, NULL); cl->done = 1; gpr_cv_signal(&cl->done_cv); - gpr_mu_unlock(&cl->mu); } /* Write as much as possible, then register notify_on_write. */ static void client_session_write(void *arg, /*client*/ - enum grpc_em_cb_status status) { + int success) { client *cl = arg; - int fd = grpc_fd_get(cl->em_fd); + int fd = cl->em_fd->fd; ssize_t write_once = 0; - if (status == GRPC_CALLBACK_CANCELLED) { - client_session_shutdown_cb(arg, GRPC_CALLBACK_SUCCESS); + if (!success) { + gpr_mu_lock(&cl->mu); + client_session_shutdown_cb(arg, 1); + gpr_mu_unlock(&cl->mu); return; } @@ -315,14 +308,10 @@ static void client_session_write(void *arg, /*client*/ if (errno == EAGAIN) { gpr_mu_lock(&cl->mu); if (cl->client_write_cnt < CLIENT_TOTAL_WRITE_CNT) { - GPR_ASSERT(grpc_fd_notify_on_write(cl->em_fd, client_session_write, cl, - gpr_inf_future)); + grpc_fd_notify_on_write(cl->em_fd, client_session_write, cl); cl->client_write_cnt++; } else { - close(fd); - grpc_fd_shutdown(cl->em_fd); - grpc_fd_notify_on_write(cl->em_fd, client_session_write, cl, - gpr_inf_future); + client_session_shutdown_cb(arg, 1); } gpr_mu_unlock(&cl->mu); } else { @@ -344,7 +333,7 @@ static void client_start(client *cl, int port) { cl->em_fd = grpc_fd_create(fd); - client_session_write(cl, GRPC_CALLBACK_SUCCESS); + client_session_write(cl, 1); } /* Wait for the signal to shutdown a client. */ @@ -378,7 +367,7 @@ static void test_grpc_fd() { typedef struct fd_change_data { gpr_mu mu; gpr_cv cv; - void (*cb_that_ran)(void *, enum grpc_em_cb_status); + void (*cb_that_ran)(void *, int success); } fd_change_data; void init_change_data(fd_change_data *fdc) { @@ -392,8 +381,7 @@ void destroy_change_data(fd_change_data *fdc) { gpr_cv_destroy(&fdc->cv); } -static void first_read_callback(void *arg /* fd_change_data */, - enum grpc_em_cb_status status) { +static void first_read_callback(void *arg /* fd_change_data */, int success) { fd_change_data *fdc = arg; gpr_mu_lock(&fdc->mu); @@ -402,8 +390,7 @@ static void first_read_callback(void *arg /* fd_change_data */, gpr_mu_unlock(&fdc->mu); } -static void second_read_callback(void *arg /* fd_change_data */, - enum grpc_em_cb_status status) { +static void second_read_callback(void *arg /* fd_change_data */, int success) { fd_change_data *fdc = arg; gpr_mu_lock(&fdc->mu); @@ -436,7 +423,7 @@ static void test_grpc_fd_change() { em_fd = grpc_fd_create(sv[0]); /* Register the first callback, then make its FD readable */ - grpc_fd_notify_on_read(em_fd, first_read_callback, &a, gpr_inf_future); + grpc_fd_notify_on_read(em_fd, first_read_callback, &a); data = 0; result = write(sv[1], &data, 1); GPR_ASSERT(result == 1); @@ -455,7 +442,7 @@ static void test_grpc_fd_change() { /* Now register a second callback with distinct change data, and do the same thing again. */ - grpc_fd_notify_on_read(em_fd, second_read_callback, &b, gpr_inf_future); + grpc_fd_notify_on_read(em_fd, second_read_callback, &b); data = 0; result = write(sv[1], &data, 1); GPR_ASSERT(result == 1); @@ -468,48 +455,9 @@ static void test_grpc_fd_change() { GPR_ASSERT(b.cb_that_ran == second_read_callback); gpr_mu_unlock(&b.mu); - grpc_fd_destroy(em_fd, NULL, NULL); + grpc_fd_orphan(em_fd, NULL, NULL); destroy_change_data(&a); destroy_change_data(&b); - close(sv[0]); - close(sv[1]); -} - -void timeout_callback(void *arg, enum grpc_em_cb_status status) { - if (status == GRPC_CALLBACK_TIMED_OUT) { - gpr_event_set(arg, (void *)1); - } else { - gpr_event_set(arg, (void *)2); - } -} - -void test_grpc_fd_notify_timeout() { - grpc_fd *em_fd; - gpr_event ev; - int flags; - int sv[2]; - gpr_timespec timeout; - gpr_timespec deadline; - - gpr_event_init(&ev); - - GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); - flags = fcntl(sv[0], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); - flags = fcntl(sv[1], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); - - em_fd = grpc_fd_create(sv[0]); - - timeout = gpr_time_from_micros(1000000); - deadline = gpr_time_add(gpr_now(), timeout); - - grpc_fd_notify_on_read(em_fd, timeout_callback, &ev, deadline); - - GPR_ASSERT(gpr_event_wait(&ev, gpr_time_add(deadline, timeout))); - - GPR_ASSERT(gpr_event_get(&ev) == (void *)1); - grpc_fd_destroy(em_fd, NULL, NULL); close(sv[1]); } @@ -518,7 +466,6 @@ int main(int argc, char **argv) { grpc_iomgr_init(); test_grpc_fd(); test_grpc_fd_change(); - test_grpc_fd_notify_timeout(); grpc_iomgr_shutdown(); return 0; } diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c index cb1cd0bc165..2d0a89a1f52 100644 --- a/test/core/iomgr/tcp_client_posix_test.c +++ b/test/core/iomgr/tcp_client_posix_test.c @@ -44,7 +44,7 @@ #include static gpr_timespec test_deadline() { - return gpr_time_add(gpr_now(), gpr_time_from_micros(1000000)); + return gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); } static void must_succeed(void *arg, grpc_endpoint *tcp) { diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 6a4ef0f9842..7fd2567cec5 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -154,7 +154,7 @@ static void read_cb(void *user_data, gpr_slice *slices, size_t nslices, if (state->read_bytes >= state->target_read_bytes) { gpr_cv_signal(&state->cv); } else { - grpc_endpoint_notify_on_read(state->ep, read_cb, state, gpr_inf_future); + grpc_endpoint_notify_on_read(state->ep, read_cb, state); } gpr_mu_unlock(&state->mu); } @@ -183,7 +183,7 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { state.read_bytes = 0; state.target_read_bytes = written_bytes; - grpc_endpoint_notify_on_read(ep, read_cb, &state, gpr_inf_future); + grpc_endpoint_notify_on_read(ep, read_cb, &state); gpr_mu_lock(&state.mu); for (;;) { @@ -225,7 +225,7 @@ static void large_read_test(ssize_t slice_size) { state.read_bytes = 0; state.target_read_bytes = written_bytes; - grpc_endpoint_notify_on_read(ep, read_cb, &state, gpr_inf_future); + grpc_endpoint_notify_on_read(ep, read_cb, &state); gpr_mu_lock(&state.mu); for (;;) { @@ -363,8 +363,8 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - if (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state, - gpr_inf_future) == GRPC_ENDPOINT_WRITE_DONE) { + if (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state) == + GRPC_ENDPOINT_WRITE_DONE) { /* Write completed immediately */ read_bytes = drain_socket(sv[0]); GPR_ASSERT(read_bytes == num_bytes); @@ -421,15 +421,13 @@ static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - switch (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state, - gpr_inf_future)) { + switch (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state)) { case GRPC_ENDPOINT_WRITE_DONE: case GRPC_ENDPOINT_WRITE_ERROR: /* Write completed immediately */ break; case GRPC_ENDPOINT_WRITE_PENDING: - grpc_endpoint_notify_on_read(ep, read_done_for_write_error, NULL, - gpr_inf_future); + grpc_endpoint_notify_on_read(ep, read_done_for_write_error, NULL); gpr_mu_lock(&state.mu); for (;;) { if (state.write_done) { diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c index cb77a880620..f30ff917cb5 100644 --- a/test/core/iomgr/tcp_server_posix_test.c +++ b/test/core/iomgr/tcp_server_posix_test.c @@ -66,7 +66,7 @@ static void test_no_op() { static void test_no_op_with_start() { grpc_tcp_server *s = grpc_tcp_server_create(); LOG_TEST(); - grpc_tcp_server_start(s, on_connect, NULL); + grpc_tcp_server_start(s, NULL, on_connect, NULL); grpc_tcp_server_destroy(s); } @@ -93,7 +93,7 @@ static void test_no_op_with_port_and_start() { GPR_ASSERT( grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr))); - grpc_tcp_server_start(s, on_connect, NULL); + grpc_tcp_server_start(s, NULL, on_connect, NULL); grpc_tcp_server_destroy(s); } @@ -120,7 +120,7 @@ static void test_connect(int n) { GPR_ASSERT(getsockname(svrfd, (struct sockaddr *)&addr, &addr_len) == 0); GPR_ASSERT(addr_len <= sizeof(addr)); - grpc_tcp_server_start(s, on_connect, NULL); + grpc_tcp_server_start(s, NULL, on_connect, NULL); for (i = 0; i < n; i++) { deadline = gpr_time_add(gpr_now(), gpr_time_from_micros(10000000)); diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index 9311d6ba119..d4baa64725f 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -153,8 +153,7 @@ static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { int verified = 0; gpr_log(GPR_INFO, "Start test left over"); - grpc_endpoint_notify_on_read(f.client_ep, verify_leftover, &verified, - gpr_inf_future); + grpc_endpoint_notify_on_read(f.client_ep, verify_leftover, &verified); GPR_ASSERT(verified == 1); grpc_endpoint_shutdown(f.client_ep); @@ -187,7 +186,7 @@ static void test_destroy_ep_early(grpc_endpoint_test_config config, grpc_endpoint_test_fixture f = config.create_fixture(slice_size); gpr_log(GPR_INFO, "Start test destroy early"); - grpc_endpoint_notify_on_read(f.client_ep, destroy_early, &f, gpr_inf_future); + grpc_endpoint_notify_on_read(f.client_ep, destroy_early, &f); grpc_endpoint_shutdown(f.server_ep); grpc_endpoint_destroy(f.server_ep); diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index ffce5f6ecd5..6cc5a8b2932 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -115,10 +115,12 @@ - + - + + + @@ -143,9 +145,9 @@ + - @@ -158,8 +160,8 @@ - + @@ -236,11 +238,15 @@ - + + + - + - + + + @@ -332,10 +338,10 @@ - - + + diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj index ffce5f6ecd5..6cc5a8b2932 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj @@ -115,10 +115,12 @@ - + - + + + @@ -143,9 +145,9 @@ + - @@ -158,8 +160,8 @@ - + @@ -236,11 +238,15 @@ - + + + - + - + + + @@ -332,10 +338,10 @@ - - + + From d9962df7a5c38d21b1413ae6ab830d671ae2cb26 Mon Sep 17 00:00:00 2001 From: ctiller Date: Wed, 7 Jan 2015 15:31:39 -0800 Subject: [PATCH 03/29] Don't log on EINTR. Change on 2015/01/07 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83469190 --- src/core/iomgr/pollset_multipoller_with_poll_posix.c | 4 +++- src/core/iomgr/pollset_posix.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c index 06c7a5a0dd3..e482da94f7c 100644 --- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c +++ b/src/core/iomgr/pollset_multipoller_with_poll_posix.c @@ -166,7 +166,9 @@ static int multipoll_with_poll_pollset_maybe_work( r = poll(h->pfds, h->pfd_count, timeout); if (r < 0) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); + if (errno != EINTR) { + gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); + } } else if (r == 0) { /* do nothing */ } else { diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index ba4031e11f4..ff00e064291 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -301,7 +301,9 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset, r = poll(pfd, GPR_ARRAY_SIZE(pfd), timeout); if (r < 0) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); + if (errno != EINTR) { + gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); + } } else if (r == 0) { /* do nothing */ } else { From c008ae5e506b7d92137d1b905117fc887036e701 Mon Sep 17 00:00:00 2001 From: ctiller Date: Wed, 7 Jan 2015 15:33:00 -0800 Subject: [PATCH 04/29] Fix opensource build. Change on 2015/01/07 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83469328 --- Makefile | 17 +---------------- templates/Makefile.template | 17 +---------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index a48e621debd..829241b9d5b 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,7 @@ CPPFLAGS += -g -fPIC -Wall -Werror -Wno-long-long LDFLAGS += -g -pthread -fPIC INCLUDES = . include gens -LIBS = rt m z event event_pthreads pthread +LIBS = rt m z pthread LIBSXX = protobuf LIBS_PROTOC = protoc protobuf @@ -143,20 +143,12 @@ else IS_GIT_FOLDER = true endif -EVENT2_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/event2.c -levent $(LDFLAGS) OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS) ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) -HAS_SYSTEM_EVENT2 = $(shell $(EVENT2_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false) -ifeq ($(wildcard third_party/libevent/include/event2/event.h),) -HAS_EMBEDDED_EVENT2 = false -else -HAS_EMBEDDED_EVENT2 = true -endif - ifeq ($(wildcard third_party/openssl/ssl/ssl.h),) HAS_EMBEDDED_OPENSSL_ALPN = false else @@ -169,12 +161,6 @@ else HAS_EMBEDDED_ZLIB = true endif -ifneq ($(SYSTEM),MINGW32) -ifeq ($(HAS_SYSTEM_EVENT2),false) -DEP_MISSING += libevent -endif -endif - ifeq ($(HAS_SYSTEM_ZLIB),false) ifeq ($(HAS_EMBEDDED_ZLIB),true) ZLIB_DEP = third_party/zlib/libz.a @@ -466,7 +452,6 @@ chttp2_socket_pair_one_byte_at_a_time_thread_stress_test: bins/$(CONFIG)/chttp2_ chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test run_dep_checks: - $(EVENT2_CHECK_CMD) || true $(OPENSSL_ALPN_CHECK_CMD) || true $(ZLIB_CHECK_CMD) || true diff --git a/templates/Makefile.template b/templates/Makefile.template index bdb97651145..44144c8f7e5 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -100,7 +100,7 @@ CPPFLAGS += -g -fPIC -Wall -Werror -Wno-long-long LDFLAGS += -g -pthread -fPIC INCLUDES = . include gens -LIBS = rt m z event event_pthreads pthread +LIBS = rt m z pthread LIBSXX = protobuf LIBS_PROTOC = protoc protobuf @@ -159,20 +159,12 @@ else IS_GIT_FOLDER = true endif -EVENT2_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/event2.c -levent $(LDFLAGS) OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS) ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) -HAS_SYSTEM_EVENT2 = $(shell $(EVENT2_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_ZLIB = $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false) -ifeq ($(wildcard third_party/libevent/include/event2/event.h),) -HAS_EMBEDDED_EVENT2 = false -else -HAS_EMBEDDED_EVENT2 = true -endif - ifeq ($(wildcard third_party/openssl/ssl/ssl.h),) HAS_EMBEDDED_OPENSSL_ALPN = false else @@ -185,12 +177,6 @@ else HAS_EMBEDDED_ZLIB = true endif -ifneq ($(SYSTEM),MINGW32) -ifeq ($(HAS_SYSTEM_EVENT2),false) -DEP_MISSING += libevent -endif -endif - ifeq ($(HAS_SYSTEM_ZLIB),false) ifeq ($(HAS_EMBEDDED_ZLIB),true) ZLIB_DEP = third_party/zlib/libz.a @@ -291,7 +277,6 @@ ${tgt.name}: bins/$(CONFIG)/${tgt.name} % endfor run_dep_checks: - $(EVENT2_CHECK_CMD) || true $(OPENSSL_ALPN_CHECK_CMD) || true $(ZLIB_CHECK_CMD) || true From 0f0a6bc4f0d58156a611f048f0ea16d632ead954 Mon Sep 17 00:00:00 2001 From: temiola Date: Wed, 7 Jan 2015 18:43:40 -0800 Subject: [PATCH 05/29] Switches to using protobuf-ruby. - Adds a dependency to protobuf-ruby in the gemfile - Updates math.proto to proto3 - Updates math server and client to use protoc protos - Updates interop server and client to use protoc protos Also - Fixes/Updates the noproto samples TESTED: math_server and math_client can communicate locally. Change on 2015/01/07 by temiola ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83483448 --- src/ruby/Gemfile | 8 -- src/ruby/README.md | 46 +-------- src/ruby/bin/interop/interop_client.rb | 25 ++--- src/ruby/bin/interop/interop_server.rb | 9 +- .../net/proto2/bridge/proto/message_set.pb.rb | 14 --- .../bin/interop/net/proto2/proto/empty.pb.rb | 12 --- .../bin/interop/test/cpp/interop/empty.rb | 44 +++++++++ .../bin/interop/test/cpp/interop/messages.rb | 86 +++++++++++++++++ src/ruby/bin/interop/test/cpp/interop/test.rb | 43 +++++++++ .../interop/test/cpp/interop/test_services.rb | 59 ++++++++++++ .../stubby/testing/proto/messages.pb.rb | 94 ------------------- .../stubby/testing/proto/test.pb.rb | 30 ------ src/ruby/bin/math.pb.rb | 65 ------------- src/ruby/bin/math.proto | 14 +-- src/ruby/bin/math.rb | 61 ++++++++++++ src/ruby/bin/math_client.rb | 6 +- src/ruby/bin/math_server.rb | 6 +- src/ruby/bin/math_services.rb | 55 +++++++++++ src/ruby/bin/noproto_client.rb | 62 +++++++++--- src/ruby/bin/noproto_server.rb | 54 +++++++++-- src/ruby/grpc.gemspec | 2 +- src/ruby/lib/grpc.rb | 1 - 22 files changed, 474 insertions(+), 322 deletions(-) delete mode 100755 src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb delete mode 100755 src/ruby/bin/interop/net/proto2/proto/empty.pb.rb create mode 100644 src/ruby/bin/interop/test/cpp/interop/empty.rb create mode 100644 src/ruby/bin/interop/test/cpp/interop/messages.rb create mode 100644 src/ruby/bin/interop/test/cpp/interop/test.rb create mode 100644 src/ruby/bin/interop/test/cpp/interop/test_services.rb delete mode 100755 src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb delete mode 100755 src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb delete mode 100755 src/ruby/bin/math.pb.rb create mode 100644 src/ruby/bin/math.rb create mode 100644 src/ruby/bin/math_services.rb diff --git a/src/ruby/Gemfile b/src/ruby/Gemfile index dc05f7946b2..597a7d4f4b0 100755 --- a/src/ruby/Gemfile +++ b/src/ruby/Gemfile @@ -1,12 +1,4 @@ source 'https://rubygems.org' -# Modify this when working locally, see README.md -# e.g, -# gem 'beefcake', path: "/usr/local/google/repos/beefcake" -# -# The default value is what's used for gRPC ruby's GCE configuration -# -gem 'beefcake', path: "/var/local/git/beefcake" - # Specify your gem's dependencies in grpc.gemspec gemspec diff --git a/src/ruby/README.md b/src/ruby/README.md index 3a5c50819b2..23aec2b20af 100755 --- a/src/ruby/README.md +++ b/src/ruby/README.md @@ -20,67 +20,25 @@ DEPENDENCIES The extension can be built and tested using [rake](https://rubygems.org/gems/rake). However, the rake-extensiontask rule is not supported on older versions of rubygems, and the necessary version of -rubygems is not available on the latest version of Goobuntu. +rubygems. This is resolved by using [RVM](https://rvm.io/) instead; install a single-user -ruby environment, and develop on the latest stable version of ruby (2.1.2). - - -* Proto code generation - -To build generate service stubs and skeletons, it's currently necessary to use -a patched version of a beefcake, a simple third-party proto2 library. This is -feature compatible with proto3 and will be replaced by official proto3 support -in protoc. - -* Patched protoc - -The patched version of beefcake in turn depends on a patched version of protoc. -This is an update of the latest open source release of protoc with some forward -looking proto3 patches. +ruby environment, and develop on the latest stable version of ruby (2.1.5). INSTALLATION PREREQUISITES -------------------------- -Install the patched protoc - -$ cd -$ git clone sso://team/one-platform-grpc-team/protobuf -$ cd protobuf -$ ./configure --prefix=/usr -$ make -$ sudo make install - -Install an update to OpenSSL with ALPN support - -$ wget https://www.openssl.org/source/openssl-1.0.2-beta3.tar.gz -$ tar -zxvf openssl-1.0.2-beta3.tar.gz -$ cd openssl-1.0.2-beta3 -$ ./config shared -$ make -$ sudo make install - Install RVM -$ # the -with-openssl-dir ensures that ruby uses the updated version of SSL $ command curl -sSL https://rvm.io/mpapis.asc | gpg --import - $ \curl -sSL https://get.rvm.io | bash -s stable --ruby $ $ # follow the instructions to ensure that your're using the latest stable version of Ruby $ # and that the rvm command is installed $ -$ rvm reinstall 2.1.5 --with-openssl-dir=/usr/local/ssl $ gem install bundler # install bundler, the standard ruby package manager -Install the patched beefcake, and update the Gemfile to reference - -$ cd -$ git clone sso://team/one-platform-grpc-team/grpc-ruby-beefcake beefcake -$ cd beefcake -$ bundle install -$ - HACKING ------- diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb index 6e7bfeef976..d0478bb4d1c 100644 --- a/src/ruby/bin/interop/interop_client.rb +++ b/src/ruby/bin/interop/interop_client.rb @@ -47,9 +47,11 @@ require 'minitest' require 'minitest/assertions' require 'grpc' +require 'google/protobuf' -require 'third_party/stubby/testing/proto/test.pb' -require 'third_party/stubby/testing/proto/messages.pb' +require 'test/cpp/interop/test_services' +require 'test/cpp/interop/messages' +require 'test/cpp/interop/empty' # loads the certificates used to access the test server securely. def load_test_certs @@ -79,7 +81,7 @@ end # produces a string of null chars (\0) of length l. def nulls(l) raise 'requires #{l} to be +ve' if l < 0 - [].pack('x' * l) + [].pack('x' * l).force_encoding('utf-8') end # a PingPongPlayer implements the ping pong bidi test. @@ -105,10 +107,11 @@ class PingPongPlayer req_size, resp_size = m req = req_cls.new(:payload => Payload.new(:body => nulls(req_size)), :response_type => COMPRESSABLE, - :response_parameters => p_cls.new(:size => resp_size)) + :response_parameters => [p_cls.new(:size => resp_size)]) yield req resp = @queue.pop - assert_equal(COMPRESSABLE, resp.payload.type, 'payload type is wrong') + assert_equal(PayloadType.lookup(COMPRESSABLE), resp.payload.type, + 'payload type is wrong') assert_equal(resp_size, resp.payload.body.length, 'payload body #{i} has the wrong length') p "OK: ping_pong #{count}" @@ -132,10 +135,10 @@ class NamedTests # TESTING # PASSED # FAIL - # ruby server: fails beefcake throws on deserializing the 0-length message + # ruby server: fails protobuf-ruby can't pass an empty message def empty_unary - resp = @stub.empty_call(Proto2::Empty.new) - assert resp.is_a?(Proto::Empty), 'empty_unary: invalid response' + resp = @stub.empty_call(Empty.new) + assert resp.is_a?(Empty), 'empty_unary: invalid response' p 'OK: empty_unary' end @@ -186,7 +189,8 @@ class NamedTests resps = @stub.streaming_output_call(req) resps.each_with_index do |r, i| assert i < msg_sizes.length, 'too many responses' - assert_equal(COMPRESSABLE, r.payload.type, 'payload type is wrong') + assert_equal(PayloadType.lookup(COMPRESSABLE), r.payload.type, + 'payload type is wrong') assert_equal(msg_sizes[i], r.payload.body.length, 'payload body #{i} has the wrong length') end @@ -197,9 +201,6 @@ class NamedTests # PASSED # ruby server # FAILED - # - # TODO(temiola): update this test to stay consistent with the java test's - # interpretation of the test spec. def ping_pong msg_sizes = [[27182, 31415], [8, 9], [1828, 2653], [45904, 58979]] ppp = PingPongPlayer.new(msg_sizes) diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb index 35d69f6fd38..53e271e80d5 100644 --- a/src/ruby/bin/interop/interop_server.rb +++ b/src/ruby/bin/interop/interop_server.rb @@ -47,8 +47,9 @@ require 'optparse' require 'grpc' -require 'third_party/stubby/testing/proto/test.pb' -require 'third_party/stubby/testing/proto/messages.pb' +require 'test/cpp/interop/test_services' +require 'test/cpp/interop/messages' +require 'test/cpp/interop/empty' # loads the certificates by the test server. def load_test_certs @@ -67,7 +68,7 @@ end # produces a string of null chars (\0) of length l. def nulls(l) raise 'requires #{l} to be +ve' if l < 0 - [].pack('x' * l) + [].pack('x' * l).force_encoding('utf-8') end # A EnumeratorQueue wraps a Queue yielding the items added to it via each_item. @@ -98,7 +99,7 @@ class TestTarget < Grpc::Testing::TestService::Service include Grpc::Testing::PayloadType def empty_call(empty, call) - Proto::Empty.new + Empty.new end def unary_call(simple_req, call) diff --git a/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb b/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb deleted file mode 100755 index eadd1d4ceb5..00000000000 --- a/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb +++ /dev/null @@ -1,14 +0,0 @@ -## Generated from net/proto2/bridge/proto/message_set.proto for proto2.bridge -require 'beefcake' - -module Proto2 - module Bridge - - class MessageSet - include Beefcake::Message - end - - class MessageSet - end - end -end diff --git a/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb b/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb deleted file mode 100755 index 2aa0c765091..00000000000 --- a/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb +++ /dev/null @@ -1,12 +0,0 @@ -## Generated from net/proto2/proto/empty.proto for proto2 -require 'beefcake' - -module Proto2 - - class Empty - include Beefcake::Message - end - - class Empty - end -end diff --git a/src/ruby/bin/interop/test/cpp/interop/empty.rb b/src/ruby/bin/interop/test/cpp/interop/empty.rb new file mode 100644 index 00000000000..acd4160d248 --- /dev/null +++ b/src/ruby/bin/interop/test/cpp/interop/empty.rb @@ -0,0 +1,44 @@ +# Copyright 2014, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: test/cpp/interop/empty.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_message "grpc.testing.Empty" do + end +end + +module Grpc + module Testing + Empty = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Empty").msgclass + end +end diff --git a/src/ruby/bin/interop/test/cpp/interop/messages.rb b/src/ruby/bin/interop/test/cpp/interop/messages.rb new file mode 100644 index 00000000000..491608bff26 --- /dev/null +++ b/src/ruby/bin/interop/test/cpp/interop/messages.rb @@ -0,0 +1,86 @@ +# Copyright 2014, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: test/cpp/interop/messages.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_message "grpc.testing.Payload" do + optional :type, :enum, 1, "grpc.testing.PayloadType" + optional :body, :string, 2 + end + add_message "grpc.testing.SimpleRequest" do + optional :response_type, :enum, 1, "grpc.testing.PayloadType" + optional :response_size, :int32, 2 + optional :payload, :message, 3, "grpc.testing.Payload" + end + add_message "grpc.testing.SimpleResponse" do + optional :payload, :message, 1, "grpc.testing.Payload" + optional :effective_gaia_user_id, :int64, 2 + end + add_message "grpc.testing.StreamingInputCallRequest" do + optional :payload, :message, 1, "grpc.testing.Payload" + end + add_message "grpc.testing.StreamingInputCallResponse" do + optional :aggregated_payload_size, :int32, 1 + end + add_message "grpc.testing.ResponseParameters" do + optional :size, :int32, 1 + optional :interval_us, :int32, 2 + end + add_message "grpc.testing.StreamingOutputCallRequest" do + optional :response_type, :enum, 1, "grpc.testing.PayloadType" + repeated :response_parameters, :message, 2, "grpc.testing.ResponseParameters" + optional :payload, :message, 3, "grpc.testing.Payload" + end + add_message "grpc.testing.StreamingOutputCallResponse" do + optional :payload, :message, 1, "grpc.testing.Payload" + end + add_enum "grpc.testing.PayloadType" do + value :COMPRESSABLE, 0 + value :UNCOMPRESSABLE, 1 + value :RANDOM, 2 + end +end + +module Grpc + module Testing + Payload = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Payload").msgclass + SimpleRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleRequest").msgclass + SimpleResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleResponse").msgclass + StreamingInputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallRequest").msgclass + StreamingInputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallResponse").msgclass + ResponseParameters = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ResponseParameters").msgclass + StreamingOutputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallRequest").msgclass + StreamingOutputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallResponse").msgclass + PayloadType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.PayloadType").enummodule + end +end diff --git a/src/ruby/bin/interop/test/cpp/interop/test.rb b/src/ruby/bin/interop/test/cpp/interop/test.rb new file mode 100644 index 00000000000..0b391ed6af0 --- /dev/null +++ b/src/ruby/bin/interop/test/cpp/interop/test.rb @@ -0,0 +1,43 @@ +# Copyright 2014, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: test/cpp/interop/test.proto + +require 'google/protobuf' + +require 'test/cpp/interop/empty' +require 'test/cpp/interop/messages' +Google::Protobuf::DescriptorPool.generated_pool.build do +end + +module Grpc + module Testing + end +end diff --git a/src/ruby/bin/interop/test/cpp/interop/test_services.rb b/src/ruby/bin/interop/test/cpp/interop/test_services.rb new file mode 100644 index 00000000000..464d5e24f65 --- /dev/null +++ b/src/ruby/bin/interop/test/cpp/interop/test_services.rb @@ -0,0 +1,59 @@ +# Copyright 2014, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Generated by the protocol buffer compiler. DO NOT EDIT! +# Source: test/cpp/interop/test.proto for package 'grpc.testing' + +require 'grpc' +require 'test/cpp/interop/test' + +module Grpc + module Testing + module TestService + + # TODO: add proto service documentation here + class Service + + include GRPC::GenericService + + self.marshal_class_method = :encode + self.unmarshal_class_method = :decode + + rpc :EmptyCall, Empty, Empty + rpc :UnaryCall, SimpleRequest, SimpleResponse + rpc :StreamingOutputCall, StreamingOutputCallRequest, stream(StreamingOutputCallResponse) + rpc :StreamingInputCall, stream(StreamingInputCallRequest), StreamingInputCallResponse + rpc :FullDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) + rpc :HalfDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) + end + + Stub = Service.rpc_stub_class + end + end +end diff --git a/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb b/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb deleted file mode 100755 index 9a913f93e58..00000000000 --- a/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb +++ /dev/null @@ -1,94 +0,0 @@ -## Generated from third_party/stubby/testing/proto/messages.proto for grpc.testing -require 'beefcake' - -require 'net/proto2/bridge/proto/message_set.pb' - -module Grpc - module Testing - - module PayloadType - COMPRESSABLE = 0 - UNCOMPRESSABLE = 1 - RANDOM = 2 - end - - class Payload - include Beefcake::Message - end - - class SimpleRequest - include Beefcake::Message - end - - class SimpleResponse - include Beefcake::Message - end - - class SimpleContext - include Beefcake::Message - end - - class StreamingInputCallRequest - include Beefcake::Message - end - - class StreamingInputCallResponse - include Beefcake::Message - end - - class ResponseParameters - include Beefcake::Message - end - - class StreamingOutputCallRequest - include Beefcake::Message - end - - class StreamingOutputCallResponse - include Beefcake::Message - end - - class Payload - optional :type, PayloadType, 1 - optional :body, :bytes, 2 - end - - class SimpleRequest - optional :response_type, PayloadType, 1 - optional :response_size, :int32, 2 - optional :payload, Payload, 3 - end - - class SimpleResponse - optional :payload, Payload, 1 - optional :effective_gaia_user_id, :int64, 2 - end - - class SimpleContext - optional :value, :string, 1 - end - - class StreamingInputCallRequest - optional :payload, Payload, 1 - end - - class StreamingInputCallResponse - optional :aggregated_payload_size, :int32, 1 - end - - class ResponseParameters - optional :size, :int32, 1 - optional :interval_us, :int32, 2 - end - - class StreamingOutputCallRequest - optional :response_type, PayloadType, 1 - repeated :response_parameters, ResponseParameters, 2 - optional :payload, Payload, 3 - end - - class StreamingOutputCallResponse - optional :payload, Payload, 1 - end - end -end diff --git a/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb b/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb deleted file mode 100755 index 2e21460fe65..00000000000 --- a/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb +++ /dev/null @@ -1,30 +0,0 @@ -## Generated from third_party/stubby/testing/proto/test.proto for grpc.testing -require 'beefcake' -require 'grpc' - -require 'third_party/stubby/testing/proto/messages.pb' -require 'net/proto2/proto/empty.pb' - -module Grpc - module Testing - - module TestService - - class Service - include GRPC::GenericService - - self.marshal_class_method = :encode - self.unmarshal_class_method = :decode - - rpc :EmptyCall, Proto2::Empty, Proto2::Empty - rpc :UnaryCall, SimpleRequest, SimpleResponse - rpc :StreamingOutputCall, StreamingOutputCallRequest, stream(StreamingOutputCallResponse) - rpc :StreamingInputCall, stream(StreamingInputCallRequest), StreamingInputCallResponse - rpc :FullDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) - rpc :HalfDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) - end - Stub = Service.rpc_stub_class - - end - end -end diff --git a/src/ruby/bin/math.pb.rb b/src/ruby/bin/math.pb.rb deleted file mode 100755 index f6976be5684..00000000000 --- a/src/ruby/bin/math.pb.rb +++ /dev/null @@ -1,65 +0,0 @@ -## Generated from bin/math.proto for math -require "beefcake" -require "grpc" - -module Math - - class DivArgs - include Beefcake::Message - end - - class DivReply - include Beefcake::Message - end - - class FibArgs - include Beefcake::Message - end - - class Num - include Beefcake::Message - end - - class FibReply - include Beefcake::Message - end - - class DivArgs - required :dividend, :int64, 1 - required :divisor, :int64, 2 - end - - class DivReply - required :quotient, :int64, 1 - required :remainder, :int64, 2 - end - - class FibArgs - optional :limit, :int64, 1 - end - - class Num - required :num, :int64, 1 - end - - class FibReply - required :count, :int64, 1 - end - - module Math - - class Service - include GRPC::GenericService - - self.marshal_class_method = :encode - self.unmarshal_class_method = :decode - - rpc :Div, DivArgs, DivReply - rpc :DivMany, stream(DivArgs), stream(DivReply) - rpc :Fib, FibArgs, stream(Num) - rpc :Sum, stream(Num), Num - end - Stub = Service.rpc_stub_class - - end -end diff --git a/src/ruby/bin/math.proto b/src/ruby/bin/math.proto index de18a502602..c49787ad54d 100755 --- a/src/ruby/bin/math.proto +++ b/src/ruby/bin/math.proto @@ -1,15 +1,15 @@ -syntax = "proto2"; +syntax = "proto3"; package math; message DivArgs { - required int64 dividend = 1; - required int64 divisor = 2; + optional int64 dividend = 1; + optional int64 divisor = 2; } message DivReply { - required int64 quotient = 1; - required int64 remainder = 2; + optional int64 quotient = 1; + optional int64 remainder = 2; } message FibArgs { @@ -17,11 +17,11 @@ message FibArgs { } message Num { - required int64 num = 1; + optional int64 num = 1; } message FibReply { - required int64 count = 1; + optional int64 count = 1; } service Math { diff --git a/src/ruby/bin/math.rb b/src/ruby/bin/math.rb new file mode 100644 index 00000000000..09d1e985864 --- /dev/null +++ b/src/ruby/bin/math.rb @@ -0,0 +1,61 @@ +# Copyright 2014, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: math.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_message "math.DivArgs" do + optional :dividend, :int64, 1 + optional :divisor, :int64, 2 + end + add_message "math.DivReply" do + optional :quotient, :int64, 1 + optional :remainder, :int64, 2 + end + add_message "math.FibArgs" do + optional :limit, :int64, 1 + end + add_message "math.Num" do + optional :num, :int64, 1 + end + add_message "math.FibReply" do + optional :count, :int64, 1 + end +end + +module Math + DivArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.DivArgs").msgclass + DivReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.DivReply").msgclass + FibArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.FibArgs").msgclass + Num = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.Num").msgclass + FibReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.FibReply").msgclass +end diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb index 8a62764c084..5cba9317f4f 100644 --- a/src/ruby/bin/math_client.rb +++ b/src/ruby/bin/math_client.rb @@ -40,7 +40,7 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' -require 'math.pb' +require 'math_services' require 'optparse' include GRPC::Core::TimeConsts @@ -111,8 +111,8 @@ def main 'secure' => false } OptionParser.new do |opts| - opts.banner = 'Usage: [--host|-h :] [--secure|-s]' - opts.on('-h', '--host', ':') do |v| + opts.banner = 'Usage: [--host :] [--secure|-s]' + opts.on('--host HOST', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb index ed39144d7aa..a0f301c3e79 100644 --- a/src/ruby/bin/math_server.rb +++ b/src/ruby/bin/math_server.rb @@ -41,7 +41,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'forwardable' require 'grpc' -require 'math.pb' +require 'math_services' require 'optparse' # Holds state for a fibonacci series @@ -168,8 +168,8 @@ def main 'secure' => false } OptionParser.new do |opts| - opts.banner = 'Usage: [--host|-h :] [--secure|-s]' - opts.on('-h', '--host', ':') do |v| + opts.banner = 'Usage: [--host :] [--secure|-s]' + opts.on('--host HOST', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| diff --git a/src/ruby/bin/math_services.rb b/src/ruby/bin/math_services.rb new file mode 100644 index 00000000000..7e056025cfa --- /dev/null +++ b/src/ruby/bin/math_services.rb @@ -0,0 +1,55 @@ +# Copyright 2014, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Generated by the protocol buffer compiler. DO NOT EDIT! +# Source: math.proto for package 'math' + +require 'grpc' +require 'math' + +module Math + module Math + + # TODO: add proto service documentation here + class Service + + include GRPC::GenericService + + self.marshal_class_method = :encode + self.unmarshal_class_method = :decode + + rpc :Div, DivArgs, DivReply + rpc :DivMany, stream(DivArgs), stream(DivReply) + rpc :Fib, FibArgs, stream(Num) + rpc :Sum, stream(Num), Num + end + + Stub = Service.rpc_stub_class + end +end diff --git a/src/ruby/bin/noproto_client.rb b/src/ruby/bin/noproto_client.rb index 29ed6d9f7cc..50ae9fb68f8 100644 --- a/src/ruby/bin/noproto_client.rb +++ b/src/ruby/bin/noproto_client.rb @@ -37,36 +37,68 @@ lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' +require 'optparse' -class EchoMsg - def marshal +class NoProtoMsg + def self.marshal(o) '' end def self.unmarshal(o) - EchoMsg.new + NoProtoMsg.new end end -class EchoService +class NoProtoService include GRPC::GenericService - rpc :AnRPC, EchoMsg, EchoMsg + rpc :AnRPC, NoProtoMsg, NoProtoMsg +end - def initialize(default_var='ignored') - end +NoProtoStub = NoProtoService.rpc_stub_class - def an_rpc(req, call) - logger.info('echo service received a request') - req - end +def load_test_certs + this_dir = File.expand_path(File.dirname(__FILE__)) + data_dir = File.join(File.dirname(this_dir), 'spec/testdata') + files = ['ca.pem', 'server1.key', 'server1.pem'] + files.map { |f| File.open(File.join(data_dir, f)).read } end -EchoStub = EchoService.rpc_stub_class +def test_creds + certs = load_test_certs + creds = GRPC::Core::Credentials.new(certs[0]) +end def main - stub = EchoStub.new('localhost:9090') - logger.info('sending an rpc') - resp = stub.an_rpc(EchoMsg.new) + options = { + 'host' => 'localhost:7071', + 'secure' => false + } + OptionParser.new do |opts| + opts.banner = 'Usage: [--host :] [--secure|-s]' + opts.on('--host HOST', ':') do |v| + options['host'] = v + end + opts.on('-s', '--secure', 'access using test creds') do |v| + options['secure'] = true + end + end.parse! + + if options['secure'] + stub_opts = { + :creds => test_creds, + GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', + } + p stub_opts + p options['host'] + stub = NoProtoStub.new(options['host'], **stub_opts) + logger.info("... connecting securely on #{options['host']}") + else + stub = NoProtoStub.new(options['host']) + logger.info("... connecting insecurely on #{options['host']}") + end + + logger.info('sending a NoProto rpc') + resp = stub.an_rpc(NoProtoMsg.new) logger.info("got a response: #{resp}") end diff --git a/src/ruby/bin/noproto_server.rb b/src/ruby/bin/noproto_server.rb index 7b74fa13ec2..d410827b22d 100644 --- a/src/ruby/bin/noproto_server.rb +++ b/src/ruby/bin/noproto_server.rb @@ -37,23 +37,24 @@ lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' +require 'optparse' -class EchoMsg - def marshal +class NoProtoMsg + def self.marshal(o) '' end def self.unmarshal(o) - EchoMsg.new + NoProtoMsg.new end end -class EchoService +class NoProtoService include GRPC::GenericService - rpc :AnRPC, EchoMsg, EchoMsg + rpc :AnRPC, NoProtoMsg, NoProtoMsg end -class Echo < EchoService +class NoProto < NoProtoService def initialize(default_var='ignored') end @@ -63,11 +64,46 @@ class Echo < EchoService end end +def load_test_certs + this_dir = File.expand_path(File.dirname(__FILE__)) + data_dir = File.join(File.dirname(this_dir), 'spec/testdata') + files = ['ca.pem', 'server1.key', 'server1.pem'] + files.map { |f| File.open(File.join(data_dir, f)).read } +end + +def test_server_creds + certs = load_test_certs + server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) +end + def main - s = GRPC::RpcServer.new() - s.add_http2_port('localhost:9090') - s.handle(Echo) + options = { + 'host' => 'localhost:9090', + 'secure' => false + } + OptionParser.new do |opts| + opts.banner = 'Usage: [--host :] [--secure|-s]' + opts.on('--host HOST', ':') do |v| + options['host'] = v + end + opts.on('-s', '--secure', 'access using test creds') do |v| + options['secure'] = true + end + end.parse! + + if options['secure'] + s = GRPC::RpcServer.new(creds: test_server_creds) + s.add_http2_port(options['host'], true) + logger.info("... running securely on #{options['host']}") + else + s = GRPC::RpcServer.new + s.add_http2_port(options['host']) + logger.info("... running insecurely on #{options['host']}") + end + + s.handle(NoProto) s.run end + main diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec index b535de49467..3e1dcd578b6 100755 --- a/src/ruby/grpc.gemspec +++ b/src/ruby/grpc.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency 'xray' s.add_dependency 'logging', '~> 1.8' - s.add_dependency 'beefcake', '~> 1.1' + s.add_dependency 'google-protobuf', '~> 3.0.0alpha' s.add_dependency 'minitest', '~> 5.4' # not a dev dependency, used by the interop tests s.add_development_dependency "bundler", "~> 1.7" diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index c7eec3388c8..81c67ec8592 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -27,7 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require 'grpc/beefcake' # extends beefcake require 'grpc/errors' require 'grpc/grpc' require 'grpc/logconfig' From 583fe99706f1c0965ae69a4bf36fa6588a956c26 Mon Sep 17 00:00:00 2001 From: temiola Date: Thu, 8 Jan 2015 09:41:31 -0800 Subject: [PATCH 06/29] Updates service.rb to ensure that the DSL specified service name is not overridden Change on 2015/01/08 by temiola ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83525675 --- src/ruby/lib/grpc/generic/service.rb | 11 +++++---- src/ruby/spec/generic/service_spec.rb | 33 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/ruby/lib/grpc/generic/service.rb b/src/ruby/lib/grpc/generic/service.rb index 6a4356fab9e..f3fe638fcef 100644 --- a/src/ruby/lib/grpc/generic/service.rb +++ b/src/ruby/lib/grpc/generic/service.rb @@ -93,6 +93,8 @@ module Google::RPC # The Dsl verifies that the types in the descriptor have both the # unmarshal and marshal methods. attr_writer(:marshal_class_method, :unmarshal_class_method) + + # This allows configuration of the service name. attr_accessor(:service_name) # Adds an RPC spec. @@ -117,8 +119,8 @@ module Google::RPC end def inherited(subclass) - # Each subclass should have distinct class variable with its own - # rpc_descs. + # Each subclass should have a distinct class variable with its own + # rpc_descs subclass.rpc_descs.merge!(rpc_descs) subclass.service_name = service_name end @@ -227,8 +229,9 @@ module Google::RPC def self.included(o) o.extend(Dsl) - # Update to the use the name including module. This can be nil e,g. when - # modules are declared dynamically. + # Update to the use the service name including module. Proivde a default + # that can be nil e,g. when modules are declared dynamically. + return unless o.service_name.nil? if o.name.nil? o.service_name = 'GenericService' else diff --git a/src/ruby/spec/generic/service_spec.rb b/src/ruby/spec/generic/service_spec.rb index dc921d89345..a8e0c6f52fe 100644 --- a/src/ruby/spec/generic/service_spec.rb +++ b/src/ruby/spec/generic/service_spec.rb @@ -108,6 +108,39 @@ describe GenericService do expect(c.rpc_descs[:AnRpc]).to be_a(GRPC::RpcDesc) end + it 'adds a default service name' do + c = Class.new do + include GenericService + end + expect(c.service_name).to eq('GenericService') + end + + it 'adds a default service name to subclasses' do + base = Class.new do + include GenericService + end + c = Class.new(base) do + end + expect(c.service_name).to eq('GenericService') + end + + it 'adds the specified service name' do + c = Class.new do + include GenericService + self.service_name = 'test.service.TestService' + end + expect(c.service_name).to eq('test.service.TestService') + end + + it 'adds the specified service name to subclasses' do + base = Class.new do + include GenericService + self.service_name = 'test.service.TestService' + end + c = Class.new(base) do + end + expect(c.service_name).to eq('test.service.TestService') + end end describe '#include' do From d6fd84aff8e14429f26eca344b7418cb73847bf2 Mon Sep 17 00:00:00 2001 From: temiola Date: Thu, 8 Jan 2015 09:59:08 -0800 Subject: [PATCH 07/29] Updates the generated ruby code to specify the service name. Change on 2015/01/08 by temiola ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83527066 --- src/compiler/ruby_generator.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc index c5c58847363..20485b47a5f 100644 --- a/src/compiler/ruby_generator.cc +++ b/src/compiler/ruby_generator.cc @@ -104,6 +104,11 @@ void PrintService(const ServiceDescriptor* service, const string& package, out->Print("\n"); out->Print("self.marshal_class_method = :encode\n"); out->Print("self.unmarshal_class_method = :decode\n"); + map pkg_vars = ListToDict({ + "service.name", service->name(), + "pkg.name", package, + }); + out->Print(pkg_vars, "self.service_name = '$pkg.name$.$service.name$'\n"); out->Print("\n"); for (int i = 0; i < service->method_count(); ++i) { PrintMethod(service->method(i), package, out); From 4dee1577fb678336a1492edbf458b2e0a4a41479 Mon Sep 17 00:00:00 2001 From: temiola Date: Thu, 8 Jan 2015 10:06:29 -0800 Subject: [PATCH 08/29] Updates the math and interop samples to use the fully-qualified method name. This bring the ruby GRPC up-to-date with the changes in [] TESTED: math client access math server OK, similarly the passing interop tests continue to pass Change on 2015/01/08 by temiola ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83527704 --- src/ruby/bin/interop/test/cpp/interop/test_services.rb | 1 + src/ruby/bin/math_services.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ruby/bin/interop/test/cpp/interop/test_services.rb b/src/ruby/bin/interop/test/cpp/interop/test_services.rb index 464d5e24f65..17b5461d3e3 100644 --- a/src/ruby/bin/interop/test/cpp/interop/test_services.rb +++ b/src/ruby/bin/interop/test/cpp/interop/test_services.rb @@ -44,6 +44,7 @@ module Grpc self.marshal_class_method = :encode self.unmarshal_class_method = :decode + self.service_name = 'grpc.testing.TestService' rpc :EmptyCall, Empty, Empty rpc :UnaryCall, SimpleRequest, SimpleResponse diff --git a/src/ruby/bin/math_services.rb b/src/ruby/bin/math_services.rb index 7e056025cfa..f6ca6fe060c 100644 --- a/src/ruby/bin/math_services.rb +++ b/src/ruby/bin/math_services.rb @@ -43,6 +43,7 @@ module Math self.marshal_class_method = :encode self.unmarshal_class_method = :decode + self.service_name = 'math.Math' rpc :Div, DivArgs, DivReply rpc :DivMany, stream(DivArgs), stream(DivReply) From 6edb547c99e42d5bf0dbea540883728a09066d4b Mon Sep 17 00:00:00 2001 From: chenw Date: Thu, 8 Jan 2015 14:04:39 -0800 Subject: [PATCH 09/29] Enable streaming test case for gRPC client in GCE. Change on 2015/01/08 by chenw ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83549959 --- test/cpp/interop/client.cc | 163 +++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index ee0f62cf20b..36bc580a96c 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -128,6 +128,152 @@ void DoLargeUnary(std::shared_ptr channel) { gpr_log(GPR_INFO, "Large unary done."); } +void DoRequestStreaming(std::shared_ptr channel) { + gpr_log(GPR_INFO, "Sending request steaming rpc ..."); + std::unique_ptr stub(TestService::NewStub(channel)); + + grpc::ClientContext context; + StreamingInputCallRequest request; + StreamingInputCallResponse response; + + std::unique_ptr> stream( + stub->StreamingInputCall(&context, &response)); + + int aggregated_payload_size = 0; + for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) { + grpc::testing::Payload* payload = request.mutable_payload(); + payload->set_body(grpc::string(request_stream_sizes[i], '\0')); + GPR_ASSERT(stream->Write(request)); + aggregated_payload_size += request_stream_sizes[i]; + } + stream->WritesDone(); + grpc::Status s = stream->Wait(); + + GPR_ASSERT(response.aggregated_payload_size() == aggregated_payload_size); + GPR_ASSERT(s.IsOk()); + gpr_log(GPR_INFO, "Request streaming done."); +} + +void DoResponseStreaming(std::shared_ptr channel) { + gpr_log(GPR_INFO, "Receiving response steaming rpc ..."); + std::unique_ptr stub(TestService::NewStub(channel)); + + grpc::ClientContext context; + StreamingOutputCallRequest request; + for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) { + ResponseParameters* response_parameter = request.add_response_parameters(); + response_parameter->set_size(response_stream_sizes[i]); + } + StreamingOutputCallResponse response; + std::unique_ptr> stream( + stub->StreamingOutputCall(&context, &request)); + + unsigned int i = 0; + while (stream->Read(&response)) { + GPR_ASSERT(response.payload().body() == + grpc::string(response_stream_sizes[i], '\0')); + ++i; + } + GPR_ASSERT(response_stream_sizes.size() == i); + grpc::Status s = stream->Wait(); + + GPR_ASSERT(s.IsOk()); + gpr_log(GPR_INFO, "Response streaming done."); +} + +void DoResponseStreamingWithSlowConsumer( + std::shared_ptr channel) { + gpr_log(GPR_INFO, "Receiving response steaming rpc with slow consumer ..."); + std::unique_ptr stub(TestService::NewStub(channel)); + + grpc::ClientContext context; + StreamingOutputCallRequest request; + + for (unsigned int i = 0; i < kNumResponseMessages; ++i) { + ResponseParameters* response_parameter = request.add_response_parameters(); + response_parameter->set_size(kResponseMessageSize); + } + StreamingOutputCallResponse response; + std::unique_ptr> stream( + stub->StreamingOutputCall(&context, &request)); + + unsigned int i = 0; + while (stream->Read(&response)) { + GPR_ASSERT(response.payload().body() == + grpc::string(kResponseMessageSize, '\0')); + gpr_log(GPR_INFO, "received message %d", i); + std::this_thread::sleep_for( + std::chrono::milliseconds(kReceiveDelayMilliSeconds)); + ++i; + } + GPR_ASSERT(kNumResponseMessages == i); + grpc::Status s = stream->Wait(); + + GPR_ASSERT(s.IsOk()); + gpr_log(GPR_INFO, "Response streaming done."); +} + +void DoHalfDuplex(std::shared_ptr channel) { + gpr_log(GPR_INFO, "Sending half-duplex streaming rpc ..."); + std::unique_ptr stub(TestService::NewStub(channel)); + + grpc::ClientContext context; + std::unique_ptr> + stream(stub->HalfDuplexCall(&context)); + + StreamingOutputCallRequest request; + ResponseParameters* response_parameter = request.add_response_parameters(); + for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) { + response_parameter->set_size(response_stream_sizes[i]); + GPR_ASSERT(stream->Write(request)); + } + stream->WritesDone(); + + unsigned int i = 0; + StreamingOutputCallResponse response; + while (stream->Read(&response)) { + GPR_ASSERT(response.payload().has_body()); + GPR_ASSERT(response.payload().body() == + grpc::string(response_stream_sizes[i], '\0')); + ++i; + } + GPR_ASSERT(response_stream_sizes.size() == i); + grpc::Status s = stream->Wait(); + GPR_ASSERT(s.IsOk()); + gpr_log(GPR_INFO, "Half-duplex streaming rpc done."); +} + +void DoPingPong(std::shared_ptr channel) { + gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc ..."); + std::unique_ptr stub(TestService::NewStub(channel)); + + grpc::ClientContext context; + std::unique_ptr> + stream(stub->FullDuplexCall(&context)); + + StreamingOutputCallRequest request; + request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); + ResponseParameters* response_parameter = request.add_response_parameters(); + grpc::testing::Payload* payload = request.mutable_payload(); + StreamingOutputCallResponse response; + for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) { + response_parameter->set_size(response_stream_sizes[i]); + payload->set_body(grpc::string(request_stream_sizes[i], '\0')); + GPR_ASSERT(stream->Write(request)); + GPR_ASSERT(stream->Read(&response)); + GPR_ASSERT(response.payload().has_body()); + GPR_ASSERT(response.payload().body() == + grpc::string(response_stream_sizes[i], '\0')); + } + + stream->WritesDone(); + GPR_ASSERT(!stream->Read(&response)); + grpc::Status s = stream->Wait(); + GPR_ASSERT(s.IsOk()); + gpr_log(GPR_INFO, "Ping pong streaming done."); +} int main(int argc, char** argv) { grpc_init(); @@ -148,6 +294,23 @@ int main(int argc, char** argv) { DoEmpty(channel); } else if (FLAGS_test_case == "large_unary") { DoLargeUnary(channel); + } else if (FLAGS_test_case == "client_streaming") { + DoRequestStreaming(channel); + } else if (FLAGS_test_case == "server_streaming") { + DoResponseStreaming(channel); + } else if (FLAGS_test_case == "slow_consumer") { + DoResponseStreamingWithSlowConsumer(channel); + } else if (FLAGS_test_case == "half_duplex") { + DoHalfDuplex(channel); + } else if (FLAGS_test_case == "ping_pong") { + DoPingPong(channel); + } else if (FLAGS_test_case == "all") { + DoEmpty(channel); + DoLargeUnary(channel); + DoRequestStreaming(channel); + DoResponseStreaming(channel); + DoHalfDuplex(channel); + DoPingPong(channel); } else { gpr_log( GPR_ERROR, From 24200d3cbca2a08c7a2b15b93f1c63efb786367d Mon Sep 17 00:00:00 2001 From: hongyu Date: Thu, 8 Jan 2015 15:13:49 -0800 Subject: [PATCH 10/29] C implementation of Census trace store and stats store for grpc C lib. Change on 2015/01/08 by hongyu ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83556470 --- Makefile | 330 +++++++++++++++++- build.json | 25 ++ include/grpc/support/time.h | 2 + src/core/channel/census_filter.c | 18 +- src/core/statistics/census_init.c | 17 +- src/core/statistics/census_rpc_stats.c | 206 ++++++++++- src/core/statistics/census_rpc_stats.h | 26 +- src/core/statistics/census_tracing.c | 149 +++++++- src/core/statistics/census_tracing.h | 59 ++++ src/core/support/time.c | 4 + test/core/end2end/gen_build_json.py | 1 + .../end2end/tests/census_simple_request.c | 176 ++++++++++ test/core/statistics/census_stub_test.c | 6 +- test/core/statistics/rpc_stats_test.c | 197 +++++++++++ test/core/statistics/trace_test.c | 158 +++++++++ vsprojects/vs2013/grpc.vcxproj | 1 + vsprojects/vs2013/grpc_unsecure.vcxproj | 1 + 17 files changed, 1341 insertions(+), 35 deletions(-) create mode 100644 src/core/statistics/census_tracing.h create mode 100644 test/core/end2end/tests/census_simple_request.c create mode 100644 test/core/statistics/rpc_stats_test.c create mode 100644 test/core/statistics/trace_test.c diff --git a/Makefile b/Makefile index 829241b9d5b..153d0924efa 100644 --- a/Makefile +++ b/Makefile @@ -288,6 +288,8 @@ grpc_channel_stack_test: bins/$(CONFIG)/grpc_channel_stack_test metadata_buffer_test: bins/$(CONFIG)/metadata_buffer_test grpc_completion_queue_test: bins/$(CONFIG)/grpc_completion_queue_test grpc_completion_queue_benchmark: bins/$(CONFIG)/grpc_completion_queue_benchmark +census_trace_store_test: bins/$(CONFIG)/census_trace_store_test +census_stats_store_test: bins/$(CONFIG)/census_stats_store_test census_window_stats_test: bins/$(CONFIG)/census_window_stats_test census_statistics_quick_test: bins/$(CONFIG)/census_statistics_quick_test census_statistics_small_log_test: bins/$(CONFIG)/census_statistics_small_log_test @@ -335,6 +337,7 @@ chttp2_fake_security_cancel_after_accept_and_writes_closed_test: bins/$(CONFIG)/ chttp2_fake_security_cancel_after_invoke_test: bins/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test chttp2_fake_security_cancel_before_invoke_test: bins/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test chttp2_fake_security_cancel_in_a_vacuum_test: bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test +chttp2_fake_security_census_simple_request_test: bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test chttp2_fake_security_disappearing_server_test: bins/$(CONFIG)/chttp2_fake_security_disappearing_server_test chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test: bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test chttp2_fake_security_early_server_shutdown_finishes_tags_test: bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test @@ -355,6 +358,7 @@ chttp2_fullstack_cancel_after_accept_and_writes_closed_test: bins/$(CONFIG)/chtt chttp2_fullstack_cancel_after_invoke_test: bins/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test chttp2_fullstack_cancel_before_invoke_test: bins/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test chttp2_fullstack_cancel_in_a_vacuum_test: bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test +chttp2_fullstack_census_simple_request_test: bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test chttp2_fullstack_disappearing_server_test: bins/$(CONFIG)/chttp2_fullstack_disappearing_server_test chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test: bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test chttp2_fullstack_early_server_shutdown_finishes_tags_test: bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test @@ -375,6 +379,7 @@ chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test: bins/$(C chttp2_simple_ssl_fullstack_cancel_after_invoke_test: bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test chttp2_simple_ssl_fullstack_cancel_before_invoke_test: bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test: bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test +chttp2_simple_ssl_fullstack_census_simple_request_test: bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test chttp2_simple_ssl_fullstack_disappearing_server_test: bins/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test: bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test: bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test @@ -395,6 +400,7 @@ chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_te chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test: bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test: bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test: bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test +chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test: bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test: bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test: bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test: bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test @@ -415,6 +421,7 @@ chttp2_socket_pair_cancel_after_accept_and_writes_closed_test: bins/$(CONFIG)/ch chttp2_socket_pair_cancel_after_invoke_test: bins/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test chttp2_socket_pair_cancel_before_invoke_test: bins/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test chttp2_socket_pair_cancel_in_a_vacuum_test: bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test +chttp2_socket_pair_census_simple_request_test: bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test chttp2_socket_pair_disappearing_server_test: bins/$(CONFIG)/chttp2_socket_pair_disappearing_server_test chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test: bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test chttp2_socket_pair_early_server_shutdown_finishes_tags_test: bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test @@ -435,6 +442,7 @@ chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test +chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test: bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test @@ -477,13 +485,13 @@ shared_cxx: dep_cxx libs/$(CONFIG)/libgrpc++.$(SHARED_EXT) privatelibs: privatelibs_c privatelibs_cxx -privatelibs_c: dep_c libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a libs/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a libs/$(CONFIG)/libend2end_test_cancel_after_accept.a libs/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a libs/$(CONFIG)/libend2end_test_cancel_after_invoke.a libs/$(CONFIG)/libend2end_test_cancel_before_invoke.a libs/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a libs/$(CONFIG)/libend2end_test_disappearing_server.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a libs/$(CONFIG)/libend2end_test_invoke_large_request.a libs/$(CONFIG)/libend2end_test_max_concurrent_streams.a libs/$(CONFIG)/libend2end_test_no_op.a libs/$(CONFIG)/libend2end_test_ping_pong_streaming.a libs/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_simple_delayed_request.a libs/$(CONFIG)/libend2end_test_simple_request.a libs/$(CONFIG)/libend2end_test_thread_stress.a libs/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a libs/$(CONFIG)/libend2end_certs.a +privatelibs_c: dep_c libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a libs/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a libs/$(CONFIG)/libend2end_test_cancel_after_accept.a libs/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a libs/$(CONFIG)/libend2end_test_cancel_after_invoke.a libs/$(CONFIG)/libend2end_test_cancel_before_invoke.a libs/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_test_disappearing_server.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a libs/$(CONFIG)/libend2end_test_invoke_large_request.a libs/$(CONFIG)/libend2end_test_max_concurrent_streams.a libs/$(CONFIG)/libend2end_test_no_op.a libs/$(CONFIG)/libend2end_test_ping_pong_streaming.a libs/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_simple_delayed_request.a libs/$(CONFIG)/libend2end_test_simple_request.a libs/$(CONFIG)/libend2end_test_thread_stress.a libs/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a libs/$(CONFIG)/libend2end_certs.a -privatelibs_cxx: dep_cxx libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a libs/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a libs/$(CONFIG)/libend2end_test_cancel_after_accept.a libs/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a libs/$(CONFIG)/libend2end_test_cancel_after_invoke.a libs/$(CONFIG)/libend2end_test_cancel_before_invoke.a libs/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a libs/$(CONFIG)/libend2end_test_disappearing_server.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a libs/$(CONFIG)/libend2end_test_invoke_large_request.a libs/$(CONFIG)/libend2end_test_max_concurrent_streams.a libs/$(CONFIG)/libend2end_test_no_op.a libs/$(CONFIG)/libend2end_test_ping_pong_streaming.a libs/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_simple_delayed_request.a libs/$(CONFIG)/libend2end_test_simple_request.a libs/$(CONFIG)/libend2end_test_thread_stress.a libs/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a libs/$(CONFIG)/libend2end_certs.a +privatelibs_cxx: dep_cxx libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a libs/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a libs/$(CONFIG)/libend2end_test_cancel_after_accept.a libs/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a libs/$(CONFIG)/libend2end_test_cancel_after_invoke.a libs/$(CONFIG)/libend2end_test_cancel_before_invoke.a libs/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_test_disappearing_server.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a libs/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a libs/$(CONFIG)/libend2end_test_invoke_large_request.a libs/$(CONFIG)/libend2end_test_max_concurrent_streams.a libs/$(CONFIG)/libend2end_test_no_op.a libs/$(CONFIG)/libend2end_test_ping_pong_streaming.a libs/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_payload.a libs/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload.a libs/$(CONFIG)/libend2end_test_simple_delayed_request.a libs/$(CONFIG)/libend2end_test_simple_request.a libs/$(CONFIG)/libend2end_test_thread_stress.a libs/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a libs/$(CONFIG)/libend2end_certs.a buildtests: buildtests_c buildtests_cxx -buildtests_c: bins_dep_c privatelibs_c bins/$(CONFIG)/grpc_byte_buffer_reader_test bins/$(CONFIG)/gpr_cancellable_test bins/$(CONFIG)/gpr_log_test bins/$(CONFIG)/gpr_useful_test bins/$(CONFIG)/gpr_cmdline_test bins/$(CONFIG)/gpr_histogram_test bins/$(CONFIG)/gpr_host_port_test bins/$(CONFIG)/gpr_slice_buffer_test bins/$(CONFIG)/gpr_slice_test bins/$(CONFIG)/gpr_string_test bins/$(CONFIG)/gpr_sync_test bins/$(CONFIG)/gpr_thd_test bins/$(CONFIG)/gpr_time_test bins/$(CONFIG)/murmur_hash_test bins/$(CONFIG)/grpc_stream_op_test bins/$(CONFIG)/alpn_test bins/$(CONFIG)/time_averaged_stats_test bins/$(CONFIG)/chttp2_stream_encoder_test bins/$(CONFIG)/hpack_table_test bins/$(CONFIG)/chttp2_stream_map_test bins/$(CONFIG)/hpack_parser_test bins/$(CONFIG)/transport_metadata_test bins/$(CONFIG)/chttp2_status_conversion_test bins/$(CONFIG)/chttp2_transport_end2end_test bins/$(CONFIG)/tcp_posix_test bins/$(CONFIG)/dualstack_socket_test bins/$(CONFIG)/no_server_test bins/$(CONFIG)/resolve_address_test bins/$(CONFIG)/sockaddr_utils_test bins/$(CONFIG)/tcp_server_posix_test bins/$(CONFIG)/tcp_client_posix_test bins/$(CONFIG)/grpc_channel_stack_test bins/$(CONFIG)/metadata_buffer_test bins/$(CONFIG)/grpc_completion_queue_test bins/$(CONFIG)/census_window_stats_test bins/$(CONFIG)/census_statistics_quick_test bins/$(CONFIG)/census_statistics_small_log_test bins/$(CONFIG)/census_statistics_performance_test bins/$(CONFIG)/census_statistics_multiple_writers_test bins/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test bins/$(CONFIG)/census_stub_test bins/$(CONFIG)/census_hash_table_test bins/$(CONFIG)/fling_server bins/$(CONFIG)/fling_client bins/$(CONFIG)/fling_test bins/$(CONFIG)/echo_server bins/$(CONFIG)/echo_client bins/$(CONFIG)/echo_test bins/$(CONFIG)/message_compress_test bins/$(CONFIG)/bin_encoder_test bins/$(CONFIG)/secure_endpoint_test bins/$(CONFIG)/httpcli_format_request_test bins/$(CONFIG)/httpcli_parser_test bins/$(CONFIG)/httpcli_test bins/$(CONFIG)/grpc_credentials_test bins/$(CONFIG)/grpc_base64_test bins/$(CONFIG)/grpc_json_token_test bins/$(CONFIG)/timeout_encoding_test bins/$(CONFIG)/fd_posix_test bins/$(CONFIG)/fling_stream_test bins/$(CONFIG)/lame_client_test bins/$(CONFIG)/alarm_test bins/$(CONFIG)/alarm_list_test bins/$(CONFIG)/alarm_heap_test bins/$(CONFIG)/time_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fake_security_disappearing_server_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fake_security_invoke_large_request_test bins/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fake_security_no_op_test bins/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test bins/$(CONFIG)/chttp2_fake_security_simple_request_test bins/$(CONFIG)/chttp2_fake_security_thread_stress_test bins/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fullstack_no_op_test bins/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_no_op_test bins/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +buildtests_c: bins_dep_c privatelibs_c bins/$(CONFIG)/grpc_byte_buffer_reader_test bins/$(CONFIG)/gpr_cancellable_test bins/$(CONFIG)/gpr_log_test bins/$(CONFIG)/gpr_useful_test bins/$(CONFIG)/gpr_cmdline_test bins/$(CONFIG)/gpr_histogram_test bins/$(CONFIG)/gpr_host_port_test bins/$(CONFIG)/gpr_slice_buffer_test bins/$(CONFIG)/gpr_slice_test bins/$(CONFIG)/gpr_string_test bins/$(CONFIG)/gpr_sync_test bins/$(CONFIG)/gpr_thd_test bins/$(CONFIG)/gpr_time_test bins/$(CONFIG)/murmur_hash_test bins/$(CONFIG)/grpc_stream_op_test bins/$(CONFIG)/alpn_test bins/$(CONFIG)/time_averaged_stats_test bins/$(CONFIG)/chttp2_stream_encoder_test bins/$(CONFIG)/hpack_table_test bins/$(CONFIG)/chttp2_stream_map_test bins/$(CONFIG)/hpack_parser_test bins/$(CONFIG)/transport_metadata_test bins/$(CONFIG)/chttp2_status_conversion_test bins/$(CONFIG)/chttp2_transport_end2end_test bins/$(CONFIG)/tcp_posix_test bins/$(CONFIG)/dualstack_socket_test bins/$(CONFIG)/no_server_test bins/$(CONFIG)/resolve_address_test bins/$(CONFIG)/sockaddr_utils_test bins/$(CONFIG)/tcp_server_posix_test bins/$(CONFIG)/tcp_client_posix_test bins/$(CONFIG)/grpc_channel_stack_test bins/$(CONFIG)/metadata_buffer_test bins/$(CONFIG)/grpc_completion_queue_test bins/$(CONFIG)/census_window_stats_test bins/$(CONFIG)/census_statistics_quick_test bins/$(CONFIG)/census_statistics_small_log_test bins/$(CONFIG)/census_statistics_performance_test bins/$(CONFIG)/census_statistics_multiple_writers_test bins/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test bins/$(CONFIG)/census_stub_test bins/$(CONFIG)/census_hash_table_test bins/$(CONFIG)/fling_server bins/$(CONFIG)/fling_client bins/$(CONFIG)/fling_test bins/$(CONFIG)/echo_server bins/$(CONFIG)/echo_client bins/$(CONFIG)/echo_test bins/$(CONFIG)/message_compress_test bins/$(CONFIG)/bin_encoder_test bins/$(CONFIG)/secure_endpoint_test bins/$(CONFIG)/httpcli_format_request_test bins/$(CONFIG)/httpcli_parser_test bins/$(CONFIG)/httpcli_test bins/$(CONFIG)/grpc_credentials_test bins/$(CONFIG)/grpc_base64_test bins/$(CONFIG)/grpc_json_token_test bins/$(CONFIG)/timeout_encoding_test bins/$(CONFIG)/fd_posix_test bins/$(CONFIG)/fling_stream_test bins/$(CONFIG)/lame_client_test bins/$(CONFIG)/alarm_test bins/$(CONFIG)/alarm_list_test bins/$(CONFIG)/alarm_heap_test bins/$(CONFIG)/time_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test bins/$(CONFIG)/chttp2_fake_security_disappearing_server_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fake_security_invoke_large_request_test bins/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fake_security_no_op_test bins/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test bins/$(CONFIG)/chttp2_fake_security_simple_request_test bins/$(CONFIG)/chttp2_fake_security_thread_stress_test bins/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fullstack_no_op_test bins/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_no_op_test bins/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test buildtests_cxx: bins_dep_cxx privatelibs_cxx bins/thread_pool_test bins/status_test bins/sync_client_async_server_test bins/qps_client bins/qps_server bins/interop_server bins/interop_client bins/end2end_test bins/channel_arguments_test @@ -622,6 +630,8 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test || ( echo test chttp2_fake_security_cancel_before_invoke_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_cancel_in_a_vacuum_test" $(Q) ./bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test || ( echo test chttp2_fake_security_cancel_in_a_vacuum_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_fake_security_census_simple_request_test" + $(Q) ./bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test || ( echo test chttp2_fake_security_census_simple_request_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_disappearing_server_test" $(Q) ./bins/$(CONFIG)/chttp2_fake_security_disappearing_server_test || ( echo test chttp2_fake_security_disappearing_server_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test" @@ -662,6 +672,8 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test || ( echo test chttp2_fullstack_cancel_before_invoke_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_cancel_in_a_vacuum_test" $(Q) ./bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test || ( echo test chttp2_fullstack_cancel_in_a_vacuum_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_fullstack_census_simple_request_test" + $(Q) ./bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test || ( echo test chttp2_fullstack_census_simple_request_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_disappearing_server_test" $(Q) ./bins/$(CONFIG)/chttp2_fullstack_disappearing_server_test || ( echo test chttp2_fullstack_disappearing_server_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test" @@ -702,6 +714,8 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test || ( echo test chttp2_simple_ssl_fullstack_cancel_before_invoke_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test" $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test || ( echo test chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_census_simple_request_test" + $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test || ( echo test chttp2_simple_ssl_fullstack_census_simple_request_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_disappearing_server_test" $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test || ( echo test chttp2_simple_ssl_fullstack_disappearing_server_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test" @@ -742,6 +756,8 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test" $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test" + $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test" $(Q) ./bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test" @@ -782,6 +798,8 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test || ( echo test chttp2_socket_pair_cancel_before_invoke_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_cancel_in_a_vacuum_test" $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test || ( echo test chttp2_socket_pair_cancel_in_a_vacuum_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_socket_pair_census_simple_request_test" + $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test || ( echo test chttp2_socket_pair_census_simple_request_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_disappearing_server_test" $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_disappearing_server_test || ( echo test chttp2_socket_pair_disappearing_server_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test" @@ -822,6 +840,8 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test || ( echo test chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test" $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test || ( echo test chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test" + $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test || ( echo test chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test" $(Q) ./bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test || ( echo test chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test" @@ -978,9 +998,9 @@ objs/$(CONFIG)/%.o : %.cc dep: dep_c dep_cxx -dep_c: deps_libgpr deps_libgrpc deps_libgrpc_unsecure deps_libgrpc_test_util deps_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request deps_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs +dep_c: deps_libgpr deps_libgrpc deps_libgrpc_unsecure deps_libgrpc_test_util deps_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_census_simple_request deps_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request deps_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs -bins_dep_c: deps_gen_hpack_tables deps_grpc_byte_buffer_reader_test deps_gpr_cancellable_test deps_gpr_log_test deps_gpr_useful_test deps_gpr_cmdline_test deps_gpr_histogram_test deps_gpr_host_port_test deps_gpr_slice_buffer_test deps_gpr_slice_test deps_gpr_string_test deps_gpr_sync_test deps_gpr_thd_test deps_gpr_time_test deps_murmur_hash_test deps_grpc_stream_op_test deps_alpn_test deps_time_averaged_stats_test deps_chttp2_stream_encoder_test deps_hpack_table_test deps_chttp2_stream_map_test deps_hpack_parser_test deps_transport_metadata_test deps_chttp2_status_conversion_test deps_chttp2_transport_end2end_test deps_tcp_posix_test deps_dualstack_socket_test deps_no_server_test deps_resolve_address_test deps_sockaddr_utils_test deps_tcp_server_posix_test deps_tcp_client_posix_test deps_grpc_channel_stack_test deps_metadata_buffer_test deps_grpc_completion_queue_test deps_grpc_completion_queue_benchmark deps_census_window_stats_test deps_census_statistics_quick_test deps_census_statistics_small_log_test deps_census_statistics_performance_test deps_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test deps_census_hash_table_test deps_fling_server deps_fling_client deps_fling_test deps_echo_server deps_echo_client deps_echo_test deps_low_level_ping_pong_benchmark deps_message_compress_test deps_bin_encoder_test deps_secure_endpoint_test deps_httpcli_format_request_test deps_httpcli_parser_test deps_httpcli_test deps_grpc_credentials_test deps_grpc_fetch_oauth2 deps_grpc_base64_test deps_grpc_json_token_test deps_timeout_encoding_test deps_fd_posix_test deps_fling_stream_test deps_lame_client_test deps_alarm_test deps_alarm_list_test deps_alarm_heap_test deps_time_test deps_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +bins_dep_c: deps_gen_hpack_tables deps_grpc_byte_buffer_reader_test deps_gpr_cancellable_test deps_gpr_log_test deps_gpr_useful_test deps_gpr_cmdline_test deps_gpr_histogram_test deps_gpr_host_port_test deps_gpr_slice_buffer_test deps_gpr_slice_test deps_gpr_string_test deps_gpr_sync_test deps_gpr_thd_test deps_gpr_time_test deps_murmur_hash_test deps_grpc_stream_op_test deps_alpn_test deps_time_averaged_stats_test deps_chttp2_stream_encoder_test deps_hpack_table_test deps_chttp2_stream_map_test deps_hpack_parser_test deps_transport_metadata_test deps_chttp2_status_conversion_test deps_chttp2_transport_end2end_test deps_tcp_posix_test deps_dualstack_socket_test deps_no_server_test deps_resolve_address_test deps_sockaddr_utils_test deps_tcp_server_posix_test deps_tcp_client_posix_test deps_grpc_channel_stack_test deps_metadata_buffer_test deps_grpc_completion_queue_test deps_grpc_completion_queue_benchmark deps_census_trace_store_test deps_census_stats_store_test deps_census_window_stats_test deps_census_statistics_quick_test deps_census_statistics_small_log_test deps_census_statistics_performance_test deps_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test deps_census_hash_table_test deps_fling_server deps_fling_client deps_fling_test deps_echo_server deps_echo_client deps_echo_test deps_low_level_ping_pong_benchmark deps_message_compress_test deps_bin_encoder_test deps_secure_endpoint_test deps_httpcli_format_request_test deps_httpcli_parser_test deps_httpcli_test deps_grpc_credentials_test deps_grpc_fetch_oauth2 deps_grpc_base64_test deps_grpc_json_token_test deps_timeout_encoding_test deps_fd_posix_test deps_fling_stream_test deps_lame_client_test deps_alarm_test deps_alarm_list_test deps_alarm_heap_test deps_time_test deps_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_census_simple_request_test deps_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_census_simple_request_test deps_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_census_simple_request_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_census_simple_request_test deps_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test dep_cxx: deps_libgrpc++ deps_libgrpc++_test_util @@ -1074,7 +1094,7 @@ ifneq ($(SYSTEM),Darwin) endif endif -clean: clean_libgpr clean_libgrpc clean_libgrpc_unsecure clean_libgrpc_test_util clean_libgrpc++ clean_libgrpc++_test_util clean_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_disappearing_server clean_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_invoke_large_request clean_libend2end_test_max_concurrent_streams clean_libend2end_test_no_op clean_libend2end_test_ping_pong_streaming clean_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_simple_delayed_request clean_libend2end_test_simple_request clean_libend2end_test_thread_stress clean_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_certs clean_gen_hpack_tables clean_cpp_plugin clean_ruby_plugin clean_grpc_byte_buffer_reader_test clean_gpr_cancellable_test clean_gpr_log_test clean_gpr_useful_test clean_gpr_cmdline_test clean_gpr_histogram_test clean_gpr_host_port_test clean_gpr_slice_buffer_test clean_gpr_slice_test clean_gpr_string_test clean_gpr_sync_test clean_gpr_thd_test clean_gpr_time_test clean_murmur_hash_test clean_grpc_stream_op_test clean_alpn_test clean_time_averaged_stats_test clean_chttp2_stream_encoder_test clean_hpack_table_test clean_chttp2_stream_map_test clean_hpack_parser_test clean_transport_metadata_test clean_chttp2_status_conversion_test clean_chttp2_transport_end2end_test clean_tcp_posix_test clean_dualstack_socket_test clean_no_server_test clean_resolve_address_test clean_sockaddr_utils_test clean_tcp_server_posix_test clean_tcp_client_posix_test clean_grpc_channel_stack_test clean_metadata_buffer_test clean_grpc_completion_queue_test clean_grpc_completion_queue_benchmark clean_census_window_stats_test clean_census_statistics_quick_test clean_census_statistics_small_log_test clean_census_statistics_performance_test clean_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_circular_buffer_test clean_census_stub_test clean_census_hash_table_test clean_fling_server clean_fling_client clean_fling_test clean_echo_server clean_echo_client clean_echo_test clean_low_level_ping_pong_benchmark clean_message_compress_test clean_bin_encoder_test clean_secure_endpoint_test clean_httpcli_format_request_test clean_httpcli_parser_test clean_httpcli_test clean_grpc_credentials_test clean_grpc_fetch_oauth2 clean_grpc_base64_test clean_grpc_json_token_test clean_timeout_encoding_test clean_fd_posix_test clean_fling_stream_test clean_lame_client_test clean_thread_pool_test clean_status_test clean_sync_client_async_server_test clean_qps_client clean_qps_server clean_interop_server clean_interop_client clean_end2end_test clean_channel_arguments_test clean_alarm_test clean_alarm_list_test clean_alarm_heap_test clean_time_test clean_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_no_op_test clean_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_no_op_test clean_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +clean: clean_libgpr clean_libgrpc clean_libgrpc_unsecure clean_libgrpc_test_util clean_libgrpc++ clean_libgrpc++_test_util clean_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_census_simple_request clean_libend2end_test_disappearing_server clean_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_invoke_large_request clean_libend2end_test_max_concurrent_streams clean_libend2end_test_no_op clean_libend2end_test_ping_pong_streaming clean_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_simple_delayed_request clean_libend2end_test_simple_request clean_libend2end_test_thread_stress clean_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_certs clean_gen_hpack_tables clean_cpp_plugin clean_ruby_plugin clean_grpc_byte_buffer_reader_test clean_gpr_cancellable_test clean_gpr_log_test clean_gpr_useful_test clean_gpr_cmdline_test clean_gpr_histogram_test clean_gpr_host_port_test clean_gpr_slice_buffer_test clean_gpr_slice_test clean_gpr_string_test clean_gpr_sync_test clean_gpr_thd_test clean_gpr_time_test clean_murmur_hash_test clean_grpc_stream_op_test clean_alpn_test clean_time_averaged_stats_test clean_chttp2_stream_encoder_test clean_hpack_table_test clean_chttp2_stream_map_test clean_hpack_parser_test clean_transport_metadata_test clean_chttp2_status_conversion_test clean_chttp2_transport_end2end_test clean_tcp_posix_test clean_dualstack_socket_test clean_no_server_test clean_resolve_address_test clean_sockaddr_utils_test clean_tcp_server_posix_test clean_tcp_client_posix_test clean_grpc_channel_stack_test clean_metadata_buffer_test clean_grpc_completion_queue_test clean_grpc_completion_queue_benchmark clean_census_trace_store_test clean_census_stats_store_test clean_census_window_stats_test clean_census_statistics_quick_test clean_census_statistics_small_log_test clean_census_statistics_performance_test clean_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_circular_buffer_test clean_census_stub_test clean_census_hash_table_test clean_fling_server clean_fling_client clean_fling_test clean_echo_server clean_echo_client clean_echo_test clean_low_level_ping_pong_benchmark clean_message_compress_test clean_bin_encoder_test clean_secure_endpoint_test clean_httpcli_format_request_test clean_httpcli_parser_test clean_httpcli_test clean_grpc_credentials_test clean_grpc_fetch_oauth2 clean_grpc_base64_test clean_grpc_json_token_test clean_timeout_encoding_test clean_fd_posix_test clean_fling_stream_test clean_lame_client_test clean_thread_pool_test clean_status_test clean_sync_client_async_server_test clean_qps_client clean_qps_server clean_interop_server clean_interop_client clean_end2end_test clean_channel_arguments_test clean_alarm_test clean_alarm_list_test clean_alarm_heap_test clean_time_test clean_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_no_op_test clean_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_no_op_test clean_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(Q) $(RM) -r deps objs libs bins gens @@ -2061,6 +2081,36 @@ clean_libend2end_test_cancel_in_a_vacuum: $(Q) $(RM) libs/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.$(SHARED_EXT) +LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_SRC = \ + test/core/end2end/tests/census_simple_request.c \ + + +LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_SRC)))) +LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_SRC)))) + +libs/$(CONFIG)/libend2end_test_census_simple_request.a: $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(AR) rcs libs/$(CONFIG)/libend2end_test_census_simple_request.a $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_OBJS) + + + + + +deps_libend2end_test_census_simple_request: $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_DEPS) + +ifneq ($(NO_DEPS),true) +-include $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_DEPS) +endif + +clean_libend2end_test_census_simple_request: + $(E) "[CLEAN] Cleaning libend2end_test_census_simple_request files" + $(Q) $(RM) $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_OBJS) + $(Q) $(RM) $(LIBEND2END_TEST_CENSUS_SIMPLE_REQUEST_DEPS) + $(Q) $(RM) libs/$(CONFIG)/libend2end_test_census_simple_request.a + $(Q) $(RM) libs/$(CONFIG)/libend2end_test_census_simple_request.$(SHARED_EXT) + + LIBEND2END_TEST_DISAPPEARING_SERVER_SRC = \ test/core/end2end/tests/disappearing_server.c \ @@ -3833,6 +3883,74 @@ clean_grpc_completion_queue_benchmark: $(Q) $(RM) bins/$(CONFIG)/grpc_completion_queue_benchmark +CENSUS_TRACE_STORE_TEST_SRC = \ + test/core/statistics/trace_test.c \ + +CENSUS_TRACE_STORE_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_TRACE_STORE_TEST_SRC)))) +CENSUS_TRACE_STORE_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CENSUS_TRACE_STORE_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/census_trace_store_test: openssl_dep_error + +else + +bins/$(CONFIG)/census_trace_store_test: $(CENSUS_TRACE_STORE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CENSUS_TRACE_STORE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/census_trace_store_test + +endif + +deps_census_trace_store_test: $(CENSUS_TRACE_STORE_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CENSUS_TRACE_STORE_TEST_DEPS) +endif +endif + +clean_census_trace_store_test: + $(E) "[CLEAN] Cleaning census_trace_store_test files" + $(Q) $(RM) $(CENSUS_TRACE_STORE_TEST_OBJS) + $(Q) $(RM) $(CENSUS_TRACE_STORE_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/census_trace_store_test + + +CENSUS_STATS_STORE_TEST_SRC = \ + test/core/statistics/rpc_stats_test.c \ + +CENSUS_STATS_STORE_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STATS_STORE_TEST_SRC)))) +CENSUS_STATS_STORE_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CENSUS_STATS_STORE_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/census_stats_store_test: openssl_dep_error + +else + +bins/$(CONFIG)/census_stats_store_test: $(CENSUS_STATS_STORE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CENSUS_STATS_STORE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/census_stats_store_test + +endif + +deps_census_stats_store_test: $(CENSUS_STATS_STORE_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CENSUS_STATS_STORE_TEST_DEPS) +endif +endif + +clean_census_stats_store_test: + $(E) "[CLEAN] Cleaning census_stats_store_test files" + $(Q) $(RM) $(CENSUS_STATS_STORE_TEST_OBJS) + $(Q) $(RM) $(CENSUS_STATS_STORE_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/census_stats_store_test + + CENSUS_WINDOW_STATS_TEST_SRC = \ test/core/statistics/window_stats_test.c \ @@ -5438,6 +5556,39 @@ clean_chttp2_fake_security_cancel_in_a_vacuum_test: $(Q) $(RM) bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test +CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_SRC = \ + +CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) +CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test: openssl_dep_error + +else + +bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test: $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test + +endif + +deps_chttp2_fake_security_census_simple_request_test: $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_DEPS) +endif +endif + +clean_chttp2_fake_security_census_simple_request_test: + $(E) "[CLEAN] Cleaning chttp2_fake_security_census_simple_request_test files" + $(Q) $(RM) $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_OBJS) + $(Q) $(RM) $(CHTTP2_FAKE_SECURITY_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test + + CHTTP2_FAKE_SECURITY_DISAPPEARING_SERVER_TEST_SRC = \ CHTTP2_FAKE_SECURITY_DISAPPEARING_SERVER_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FAKE_SECURITY_DISAPPEARING_SERVER_TEST_SRC)))) @@ -6098,6 +6249,39 @@ clean_chttp2_fullstack_cancel_in_a_vacuum_test: $(Q) $(RM) bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test +CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC = \ + +CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) +CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test: openssl_dep_error + +else + +bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test: $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test + +endif + +deps_chttp2_fullstack_census_simple_request_test: $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) +endif +endif + +clean_chttp2_fullstack_census_simple_request_test: + $(E) "[CLEAN] Cleaning chttp2_fullstack_census_simple_request_test files" + $(Q) $(RM) $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) + $(Q) $(RM) $(CHTTP2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test + + CHTTP2_FULLSTACK_DISAPPEARING_SERVER_TEST_SRC = \ CHTTP2_FULLSTACK_DISAPPEARING_SERVER_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FULLSTACK_DISAPPEARING_SERVER_TEST_SRC)))) @@ -6758,6 +6942,39 @@ clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test: $(Q) $(RM) bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test +CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC = \ + +CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) +CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test: openssl_dep_error + +else + +bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test: $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test + +endif + +deps_chttp2_simple_ssl_fullstack_census_simple_request_test: $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) +endif +endif + +clean_chttp2_simple_ssl_fullstack_census_simple_request_test: + $(E) "[CLEAN] Cleaning chttp2_simple_ssl_fullstack_census_simple_request_test files" + $(Q) $(RM) $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) + $(Q) $(RM) $(CHTTP2_SIMPLE_SSL_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test + + CHTTP2_SIMPLE_SSL_FULLSTACK_DISAPPEARING_SERVER_TEST_SRC = \ CHTTP2_SIMPLE_SSL_FULLSTACK_DISAPPEARING_SERVER_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_FULLSTACK_DISAPPEARING_SERVER_TEST_SRC)))) @@ -7418,6 +7635,39 @@ clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test: $(Q) $(RM) bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test +CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC = \ + +CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) +CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test: openssl_dep_error + +else + +bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test: $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test + +endif + +deps_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test: $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) +endif +endif + +clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test: + $(E) "[CLEAN] Cleaning chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test files" + $(Q) $(RM) $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_OBJS) + $(Q) $(RM) $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test + + CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_DISAPPEARING_SERVER_TEST_SRC = \ CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_DISAPPEARING_SERVER_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_DISAPPEARING_SERVER_TEST_SRC)))) @@ -8078,6 +8328,39 @@ clean_chttp2_socket_pair_cancel_in_a_vacuum_test: $(Q) $(RM) bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test +CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_SRC = \ + +CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) +CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test: openssl_dep_error + +else + +bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test: $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test + +endif + +deps_chttp2_socket_pair_census_simple_request_test: $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_DEPS) +endif +endif + +clean_chttp2_socket_pair_census_simple_request_test: + $(E) "[CLEAN] Cleaning chttp2_socket_pair_census_simple_request_test files" + $(Q) $(RM) $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_OBJS) + $(Q) $(RM) $(CHTTP2_SOCKET_PAIR_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test + + CHTTP2_SOCKET_PAIR_DISAPPEARING_SERVER_TEST_SRC = \ CHTTP2_SOCKET_PAIR_DISAPPEARING_SERVER_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_DISAPPEARING_SERVER_TEST_SRC)))) @@ -8738,6 +9021,39 @@ clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test: $(Q) $(RM) bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test +CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_SRC = \ + +CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) +CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test: openssl_dep_error + +else + +bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test: $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_OBJS) libs/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a libs/$(CONFIG)/libend2end_test_census_simple_request.a libs/$(CONFIG)/libend2end_certs.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test + +endif + +deps_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test: $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_DEPS) +endif +endif + +clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test: + $(E) "[CLEAN] Cleaning chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test files" + $(Q) $(RM) $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_OBJS) + $(Q) $(RM) $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CENSUS_SIMPLE_REQUEST_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test + + CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_DISAPPEARING_SERVER_TEST_SRC = \ CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_DISAPPEARING_SERVER_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_DISAPPEARING_SERVER_TEST_SRC)))) @@ -9237,4 +9553,4 @@ clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_ -.PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx clean dep_c dep_cxx bins_dep_c bins_dep_cxx deps_libgpr clean_libgpr deps_libgrpc clean_libgrpc deps_libgrpc_unsecure clean_libgrpc_unsecure deps_libgrpc_test_util clean_libgrpc_test_util deps_libgrpc++ clean_libgrpc++ deps_libgrpc++_test_util clean_libgrpc++_test_util deps_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_disappearing_server clean_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request clean_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams clean_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op clean_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming clean_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request clean_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request clean_libend2end_test_simple_request deps_libend2end_test_thread_stress clean_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs clean_libend2end_certs deps_gen_hpack_tables clean_gen_hpack_tables deps_cpp_plugin clean_cpp_plugin deps_ruby_plugin clean_ruby_plugin deps_grpc_byte_buffer_reader_test clean_grpc_byte_buffer_reader_test deps_gpr_cancellable_test clean_gpr_cancellable_test deps_gpr_log_test clean_gpr_log_test deps_gpr_useful_test clean_gpr_useful_test deps_gpr_cmdline_test clean_gpr_cmdline_test deps_gpr_histogram_test clean_gpr_histogram_test deps_gpr_host_port_test clean_gpr_host_port_test deps_gpr_slice_buffer_test clean_gpr_slice_buffer_test deps_gpr_slice_test clean_gpr_slice_test deps_gpr_string_test clean_gpr_string_test deps_gpr_sync_test clean_gpr_sync_test deps_gpr_thd_test clean_gpr_thd_test deps_gpr_time_test clean_gpr_time_test deps_murmur_hash_test clean_murmur_hash_test deps_grpc_stream_op_test clean_grpc_stream_op_test deps_alpn_test clean_alpn_test deps_time_averaged_stats_test clean_time_averaged_stats_test deps_chttp2_stream_encoder_test clean_chttp2_stream_encoder_test deps_hpack_table_test clean_hpack_table_test deps_chttp2_stream_map_test clean_chttp2_stream_map_test deps_hpack_parser_test clean_hpack_parser_test deps_transport_metadata_test clean_transport_metadata_test deps_chttp2_status_conversion_test clean_chttp2_status_conversion_test deps_chttp2_transport_end2end_test clean_chttp2_transport_end2end_test deps_tcp_posix_test clean_tcp_posix_test deps_dualstack_socket_test clean_dualstack_socket_test deps_no_server_test clean_no_server_test deps_resolve_address_test clean_resolve_address_test deps_sockaddr_utils_test clean_sockaddr_utils_test deps_tcp_server_posix_test clean_tcp_server_posix_test deps_tcp_client_posix_test clean_tcp_client_posix_test deps_grpc_channel_stack_test clean_grpc_channel_stack_test deps_metadata_buffer_test clean_metadata_buffer_test deps_grpc_completion_queue_test clean_grpc_completion_queue_test deps_grpc_completion_queue_benchmark clean_grpc_completion_queue_benchmark deps_census_window_stats_test clean_census_window_stats_test deps_census_statistics_quick_test clean_census_statistics_quick_test deps_census_statistics_small_log_test clean_census_statistics_small_log_test deps_census_statistics_performance_test clean_census_statistics_performance_test deps_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test clean_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test clean_census_stub_test deps_census_hash_table_test clean_census_hash_table_test deps_fling_server clean_fling_server deps_fling_client clean_fling_client deps_fling_test clean_fling_test deps_echo_server clean_echo_server deps_echo_client clean_echo_client deps_echo_test clean_echo_test deps_low_level_ping_pong_benchmark clean_low_level_ping_pong_benchmark deps_message_compress_test clean_message_compress_test deps_bin_encoder_test clean_bin_encoder_test deps_secure_endpoint_test clean_secure_endpoint_test deps_httpcli_format_request_test clean_httpcli_format_request_test deps_httpcli_parser_test clean_httpcli_parser_test deps_httpcli_test clean_httpcli_test deps_grpc_credentials_test clean_grpc_credentials_test deps_grpc_fetch_oauth2 clean_grpc_fetch_oauth2 deps_grpc_base64_test clean_grpc_base64_test deps_grpc_json_token_test clean_grpc_json_token_test deps_timeout_encoding_test clean_timeout_encoding_test deps_fd_posix_test clean_fd_posix_test deps_fling_stream_test clean_fling_stream_test deps_lame_client_test clean_lame_client_test deps_thread_pool_test clean_thread_pool_test deps_status_test clean_status_test deps_sync_client_async_server_test clean_sync_client_async_server_test deps_qps_client clean_qps_client deps_qps_server clean_qps_server deps_interop_server clean_interop_server deps_interop_client clean_interop_client deps_end2end_test clean_end2end_test deps_channel_arguments_test clean_channel_arguments_test deps_alarm_test clean_alarm_test deps_alarm_list_test clean_alarm_list_test deps_alarm_heap_test clean_alarm_heap_test deps_time_test clean_time_test deps_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test clean_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test clean_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +.PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx clean dep_c dep_cxx bins_dep_c bins_dep_cxx deps_libgpr clean_libgpr deps_libgrpc clean_libgrpc deps_libgrpc_unsecure clean_libgrpc_unsecure deps_libgrpc_test_util clean_libgrpc_test_util deps_libgrpc++ clean_libgrpc++ deps_libgrpc++_test_util clean_libgrpc++_test_util deps_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_census_simple_request clean_libend2end_test_census_simple_request deps_libend2end_test_disappearing_server clean_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request clean_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams clean_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op clean_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming clean_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request clean_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request clean_libend2end_test_simple_request deps_libend2end_test_thread_stress clean_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs clean_libend2end_certs deps_gen_hpack_tables clean_gen_hpack_tables deps_cpp_plugin clean_cpp_plugin deps_ruby_plugin clean_ruby_plugin deps_grpc_byte_buffer_reader_test clean_grpc_byte_buffer_reader_test deps_gpr_cancellable_test clean_gpr_cancellable_test deps_gpr_log_test clean_gpr_log_test deps_gpr_useful_test clean_gpr_useful_test deps_gpr_cmdline_test clean_gpr_cmdline_test deps_gpr_histogram_test clean_gpr_histogram_test deps_gpr_host_port_test clean_gpr_host_port_test deps_gpr_slice_buffer_test clean_gpr_slice_buffer_test deps_gpr_slice_test clean_gpr_slice_test deps_gpr_string_test clean_gpr_string_test deps_gpr_sync_test clean_gpr_sync_test deps_gpr_thd_test clean_gpr_thd_test deps_gpr_time_test clean_gpr_time_test deps_murmur_hash_test clean_murmur_hash_test deps_grpc_stream_op_test clean_grpc_stream_op_test deps_alpn_test clean_alpn_test deps_time_averaged_stats_test clean_time_averaged_stats_test deps_chttp2_stream_encoder_test clean_chttp2_stream_encoder_test deps_hpack_table_test clean_hpack_table_test deps_chttp2_stream_map_test clean_chttp2_stream_map_test deps_hpack_parser_test clean_hpack_parser_test deps_transport_metadata_test clean_transport_metadata_test deps_chttp2_status_conversion_test clean_chttp2_status_conversion_test deps_chttp2_transport_end2end_test clean_chttp2_transport_end2end_test deps_tcp_posix_test clean_tcp_posix_test deps_dualstack_socket_test clean_dualstack_socket_test deps_no_server_test clean_no_server_test deps_resolve_address_test clean_resolve_address_test deps_sockaddr_utils_test clean_sockaddr_utils_test deps_tcp_server_posix_test clean_tcp_server_posix_test deps_tcp_client_posix_test clean_tcp_client_posix_test deps_grpc_channel_stack_test clean_grpc_channel_stack_test deps_metadata_buffer_test clean_metadata_buffer_test deps_grpc_completion_queue_test clean_grpc_completion_queue_test deps_grpc_completion_queue_benchmark clean_grpc_completion_queue_benchmark deps_census_trace_store_test clean_census_trace_store_test deps_census_stats_store_test clean_census_stats_store_test deps_census_window_stats_test clean_census_window_stats_test deps_census_statistics_quick_test clean_census_statistics_quick_test deps_census_statistics_small_log_test clean_census_statistics_small_log_test deps_census_statistics_performance_test clean_census_statistics_performance_test deps_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test clean_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test clean_census_stub_test deps_census_hash_table_test clean_census_hash_table_test deps_fling_server clean_fling_server deps_fling_client clean_fling_client deps_fling_test clean_fling_test deps_echo_server clean_echo_server deps_echo_client clean_echo_client deps_echo_test clean_echo_test deps_low_level_ping_pong_benchmark clean_low_level_ping_pong_benchmark deps_message_compress_test clean_message_compress_test deps_bin_encoder_test clean_bin_encoder_test deps_secure_endpoint_test clean_secure_endpoint_test deps_httpcli_format_request_test clean_httpcli_format_request_test deps_httpcli_parser_test clean_httpcli_parser_test deps_httpcli_test clean_httpcli_test deps_grpc_credentials_test clean_grpc_credentials_test deps_grpc_fetch_oauth2 clean_grpc_fetch_oauth2 deps_grpc_base64_test clean_grpc_base64_test deps_grpc_json_token_test clean_grpc_json_token_test deps_timeout_encoding_test clean_timeout_encoding_test deps_fd_posix_test clean_fd_posix_test deps_fling_stream_test clean_fling_stream_test deps_lame_client_test clean_lame_client_test deps_thread_pool_test clean_thread_pool_test deps_status_test clean_status_test deps_sync_client_async_server_test clean_sync_client_async_server_test deps_qps_client clean_qps_client deps_qps_server clean_qps_server deps_interop_server clean_interop_server deps_interop_client clean_interop_client deps_end2end_test clean_end2end_test deps_channel_arguments_test clean_channel_arguments_test deps_alarm_test clean_alarm_test deps_alarm_list_test clean_alarm_list_test deps_alarm_heap_test clean_alarm_heap_test deps_time_test clean_time_test deps_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_census_simple_request_test deps_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test clean_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_census_simple_request_test deps_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test clean_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_census_simple_request_test deps_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test diff --git a/build.json b/build.json index e0e05c8eaf4..d60f4e5705c 100644 --- a/build.json +++ b/build.json @@ -141,6 +141,7 @@ "src/core/statistics/census_interface.h", "src/core/statistics/census_log.h", "src/core/statistics/census_rpc_stats.h", + "src/core/statistics/census_tracing.h", "src/core/statistics/hash_table.h", "src/core/statistics/window_stats.h", "src/core/surface/call.h", @@ -847,6 +848,30 @@ "gpr" ] }, + { + "name": "census_trace_store_test", + "build": "executable", + "src": [ + "test/core/statistics/trace_test.c" + ], + "deps": [ + "grpc_test_util", + "grpc", + "gpr" + ] + }, + { + "name": "census_stats_store_test", + "build": "executable", + "src": [ + "test/core/statistics/rpc_stats_test.c" + ], + "deps": [ + "grpc_test_util", + "grpc", + "gpr" + ] + }, { "name": "census_window_stats_test", "build": "test", diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h index 41d1e88dc94..d5ab9f53052 100644 --- a/include/grpc/support/time.h +++ b/include/grpc/support/time.h @@ -107,6 +107,8 @@ struct timeval gpr_timeval_from_timespec(gpr_timespec t); gpr_timespec gpr_timespec_from_timeval(struct timeval t); +double gpr_timespec_to_micros(gpr_timespec t); + #ifdef __cplusplus } #endif diff --git a/src/core/channel/census_filter.c b/src/core/channel/census_filter.c index d610a6fc9d6..2799bded8a6 100644 --- a/src/core/channel/census_filter.c +++ b/src/core/channel/census_filter.c @@ -60,13 +60,11 @@ static void init_rpc_stats(census_rpc_stats* stats) { stats->cnt = 1; } -static double gpr_timespec_to_micros(gpr_timespec t) { - return t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3; -} - static void extract_and_annotate_method_tag(grpc_call_op* op, call_data* calld, channel_data* chand) { if (op->data.metadata->key == chand->path_str) { + gpr_log(GPR_DEBUG, + (const char*)GPR_SLICE_START_PTR(op->data.metadata->value->slice)); census_add_method_tag(calld->op_id, (const char*)GPR_SLICE_START_PTR( op->data.metadata->value->slice)); } @@ -78,7 +76,7 @@ static void client_call_op(grpc_call_element* elem, channel_data* chand = elem->channel_data; GPR_ASSERT(calld != NULL); GPR_ASSERT(chand != NULL); - GPR_ASSERT((calld->op_id.upper != 0) && (calld->op_id.lower != 0)); + GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); switch (op->type) { case GRPC_SEND_METADATA: extract_and_annotate_method_tag(op, calld, chand); @@ -99,7 +97,7 @@ static void server_call_op(grpc_call_element* elem, channel_data* chand = elem->channel_data; GPR_ASSERT(calld != NULL); GPR_ASSERT(chand != NULL); - GPR_ASSERT((calld->op_id.upper != 0) && (calld->op_id.lower != 0)); + GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); switch (op->type) { case GRPC_RECV_METADATA: extract_and_annotate_method_tag(op, calld, chand); @@ -171,7 +169,13 @@ static void init_channel_elem(grpc_channel_element* elem, chand->path_str = grpc_mdstr_from_string(mdctx, ":path"); } -static void destroy_channel_elem(grpc_channel_element* elem) {} +static void destroy_channel_elem(grpc_channel_element* elem) { + channel_data* chand = elem->channel_data; + GPR_ASSERT(chand != NULL); + if (chand->path_str != NULL) { + grpc_mdstr_unref(chand->path_str); + } +} const grpc_channel_filter grpc_client_census_filter = { client_call_op, channel_op, diff --git a/src/core/statistics/census_init.c b/src/core/statistics/census_init.c index 340214f8f55..bcb9ff9ad4e 100644 --- a/src/core/statistics/census_init.c +++ b/src/core/statistics/census_init.c @@ -33,5 +33,18 @@ #include "src/core/statistics/census_interface.h" -void census_init() {} -void census_shutdown() {} +#include +#include "src/core/statistics/census_rpc_stats.h" +#include "src/core/statistics/census_tracing.h" + +void census_init() { + gpr_log(GPR_INFO, "Initialize census library."); + census_tracing_init(); + census_stats_store_init(); +} + +void census_shutdown() { + gpr_log(GPR_INFO, "Shutdown census library."); + census_stats_store_shutdown(); + census_tracing_shutdown(); +} diff --git a/src/core/statistics/census_rpc_stats.c b/src/core/statistics/census_rpc_stats.c index 28101ac734d..a1ac2abff3b 100644 --- a/src/core/statistics/census_rpc_stats.c +++ b/src/core/statistics/census_rpc_stats.c @@ -35,7 +35,85 @@ #include "src/core/statistics/census_interface.h" #include "src/core/statistics/census_rpc_stats.h" +#include "src/core/statistics/hash_table.h" +#include "src/core/statistics/census_tracing.h" +#include "src/core/statistics/window_stats.h" +#include "src/core/support/murmur_hash.h" #include +#include +#include +#include + +#define NUM_INTERVALS 3 +#define MINUTE_INTERVAL 0 +#define HOUR_INTERVAL 1 +#define TOTAL_INTERVAL 2 + +/* for easier typing */ +typedef census_per_method_rpc_stats per_method_stats; + +/* Ensure mu is only initialized once. */ +static gpr_once g_stats_store_mu_init = GPR_ONCE_INIT; +/* Guards two stats stores. */ +static gpr_mu g_mu; +static census_ht* g_client_stats_store = NULL; +static census_ht* g_server_stats_store = NULL; + +static void init_mutex() { gpr_mu_init(&g_mu); } + +static void init_mutex_once() { + gpr_once_init(&g_stats_store_mu_init, init_mutex); +} + +static int cmp_str_keys(const void* k1, const void* k2) { + return strcmp((const char*)k1, (const char*)k2); +} + +/* TODO(hongyu): replace it with cityhash64 */ +static gpr_uint64 simple_hash(const void* k) { + size_t len = strlen(k); + gpr_uint64 higher = gpr_murmur_hash3((const char*)k, len / 2, 0); + return higher << 32 | + gpr_murmur_hash3((const char*)k + len / 2, len - len / 2, 0); +} + +static void delete_stats(void* stats) { + census_window_stats_destroy((struct census_window_stats*)stats); +} + +static void delete_key(void* key) { gpr_free(key); } + +static const census_ht_option ht_opt = { + CENSUS_HT_POINTER /* key type */, 1999 /* n_of_buckets */, + simple_hash /* hash function */, cmp_str_keys /* key comparator */, + delete_stats /* data deleter */, delete_key /* key deleter */}; + +static void init_rpc_stats(void* stats) { + memset(stats, 0, sizeof(census_rpc_stats)); +} + +static void stat_add_proportion(double p, void* base, const void* addme) { + census_rpc_stats* b = (census_rpc_stats*)base; + census_rpc_stats* a = (census_rpc_stats*)addme; + b->cnt += p * a->cnt; + b->rpc_error_cnt += p * a->rpc_error_cnt; + b->app_error_cnt += p * a->app_error_cnt; + b->elapsed_time_ms += p * a->elapsed_time_ms; + b->api_request_bytes += p * a->api_request_bytes; + b->wire_request_bytes += p * a->wire_request_bytes; + b->api_response_bytes += p * a->api_response_bytes; + b->wire_response_bytes += p * a->wire_response_bytes; +} + +static void stat_add(void* base, const void* addme) { + stat_add_proportion(1.0, base, addme); +} + +static gpr_timespec min_hour_total_intervals[3] = { + {60, 0}, {3600, 0}, {36000000, 0}}; + +static const census_window_stats_stat_info window_stats_settings = { + sizeof(census_rpc_stats), init_rpc_stats, stat_add, stat_add_proportion}; census_rpc_stats* census_rpc_stats_create_empty() { census_rpc_stats* ret = @@ -44,14 +122,132 @@ census_rpc_stats* census_rpc_stats_create_empty() { return ret; } -void census_aggregated_rpc_stats_destroy(census_aggregated_rpc_stats* data) {} +void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats* data) { + int i = 0; + for (i = 0; i < data->num_entries; i++) { + if (data->stats[i].method != NULL) { + gpr_free((void*)data->stats[i].method); + } + } + if (data->stats != NULL) { + gpr_free(data->stats); + } + data->num_entries = 0; + data->stats = NULL; +} + +static void record_stats(census_ht* store, census_op_id op_id, + const census_rpc_stats* stats) { + gpr_mu_lock(&g_mu); + if (store != NULL) { + trace_obj* trace = NULL; + census_internal_lock_trace_store(); + trace = census_get_trace_obj_locked(op_id); + if (trace != NULL) { + const char* method_name = census_get_trace_method_name(trace); + struct census_window_stats* window_stats = NULL; + census_ht_key key; + key.ptr = (void*)method_name; + window_stats = census_ht_find(store, key); + census_internal_unlock_trace_store(); + if (window_stats == NULL) { + window_stats = census_window_stats_create(3, min_hour_total_intervals, + 30, &window_stats_settings); + key.ptr = gpr_strdup(key.ptr); + census_ht_insert(store, key, (void*)window_stats); + } + census_window_stats_add(window_stats, gpr_now(), stats); + } else { + census_internal_unlock_trace_store(); + } + } + gpr_mu_unlock(&g_mu); +} void census_record_rpc_client_stats(census_op_id op_id, - const census_rpc_stats* stats) {} + const census_rpc_stats* stats) { + record_stats(g_client_stats_store, op_id, stats); +} void census_record_rpc_server_stats(census_op_id op_id, - const census_rpc_stats* stats) {} + const census_rpc_stats* stats) { + record_stats(g_server_stats_store, op_id, stats); +} -void census_get_server_stats(census_aggregated_rpc_stats* data) {} +/* Get stats from input stats store */ +static void get_stats(census_ht* store, census_aggregated_rpc_stats* data) { + GPR_ASSERT(data != NULL); + if (data->num_entries != 0) { + census_aggregated_rpc_stats_set_empty(data); + } + gpr_mu_lock(&g_mu); + if (store != NULL) { + size_t n; + int i, j; + gpr_timespec now = gpr_now(); + census_ht_kv* kv = census_ht_get_all_elements(store, &n); + if (kv != NULL) { + data->num_entries = n; + data->stats = (per_method_stats*)gpr_malloc(sizeof(per_method_stats) * n); + for (i = 0; i < n; i++) { + census_window_stats_sums sums[NUM_INTERVALS]; + for (j = 0; j < NUM_INTERVALS; j++) { + sums[j].statistic = (void*)census_rpc_stats_create_empty(); + } + data->stats[i].method = gpr_strdup(kv[i].k.ptr); + census_window_stats_get_sums(kv[i].v, now, sums); + data->stats[i].minute_stats = + *(census_rpc_stats*)sums[MINUTE_INTERVAL].statistic; + data->stats[i].hour_stats = + *(census_rpc_stats*)sums[HOUR_INTERVAL].statistic; + data->stats[i].total_stats = + *(census_rpc_stats*)sums[TOTAL_INTERVAL].statistic; + for (j = 0; j < NUM_INTERVALS; j++) { + gpr_free(sums[j].statistic); + } + } + gpr_free(kv); + } + } + gpr_mu_unlock(&g_mu); +} + +void census_get_client_stats(census_aggregated_rpc_stats* data) { + get_stats(g_client_stats_store, data); +} + +void census_get_server_stats(census_aggregated_rpc_stats* data) { + get_stats(g_server_stats_store, data); +} + +void census_stats_store_init() { + gpr_log(GPR_INFO, "Initialize census stats store."); + init_mutex_once(); + gpr_mu_lock(&g_mu); + if (g_client_stats_store == NULL && g_server_stats_store == NULL) { + g_client_stats_store = census_ht_create(&ht_opt); + g_server_stats_store = census_ht_create(&ht_opt); + } else { + gpr_log(GPR_ERROR, "Census stats store already initialized."); + } + gpr_mu_unlock(&g_mu); +} -void census_get_client_stats(census_aggregated_rpc_stats* data) {} +void census_stats_store_shutdown() { + gpr_log(GPR_INFO, "Shutdown census stats store."); + init_mutex_once(); + gpr_mu_lock(&g_mu); + if (g_client_stats_store != NULL) { + census_ht_destroy(g_client_stats_store); + g_client_stats_store = NULL; + } else { + gpr_log(GPR_ERROR, "Census server stats store not initialized."); + } + if (g_server_stats_store != NULL) { + census_ht_destroy(g_server_stats_store); + g_server_stats_store = NULL; + } else { + gpr_log(GPR_ERROR, "Census client stats store not initialized."); + } + gpr_mu_unlock(&g_mu); +} diff --git a/src/core/statistics/census_rpc_stats.h b/src/core/statistics/census_rpc_stats.h index 6ab7614805e..e1ff3ac31b7 100644 --- a/src/core/statistics/census_rpc_stats.h +++ b/src/core/statistics/census_rpc_stats.h @@ -37,6 +37,10 @@ #include "src/core/statistics/census_interface.h" #include +#ifdef __cplusplus +extern "C" { +#endif + struct census_rpc_stats { gpr_uint64 cnt; gpr_uint64 rpc_error_cnt; @@ -51,19 +55,20 @@ struct census_rpc_stats { /* Creates an empty rpc stats object on heap. */ census_rpc_stats* census_rpc_stats_create_empty(); -typedef struct census_per_service_per_method_rpc_stats { - const char* service; +typedef struct census_per_method_rpc_stats { const char* method; - census_rpc_stats data; -} census_per_service_per_method_rpc_stats; + census_rpc_stats minute_stats; /* cumulative stats in the past minute */ + census_rpc_stats hour_stats; /* cumulative stats in the past hour */ + census_rpc_stats total_stats; /* cumulative stats from last gc */ +} census_per_method_rpc_stats; typedef struct census_aggregated_rpc_stats { int num_entries; - census_per_service_per_method_rpc_stats* stats; + census_per_method_rpc_stats* stats; } census_aggregated_rpc_stats; -/* Deletes aggregated data. */ -void census_aggregated_rpc_stats_destroy(census_aggregated_rpc_stats* data); +/* Initializes an aggregated rpc stats object to an empty state. */ +void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats* data); /* Records client side stats of a rpc. */ void census_record_rpc_client_stats(census_op_id op_id, @@ -86,4 +91,11 @@ void census_get_server_stats(census_aggregated_rpc_stats* data_map); DO NOT CALL from outside of grpc code. */ void census_get_client_stats(census_aggregated_rpc_stats* data_map); +void census_stats_store_init(); +void census_stats_store_shutdown(); + +#ifdef __cplusplus +} +#endif + #endif /* __GRPC_INTERNAL_STATISTICS_CENSUS_RPC_STATS_H__ */ diff --git a/src/core/statistics/census_tracing.c b/src/core/statistics/census_tracing.c index d0c90328378..d37c427c5b2 100644 --- a/src/core/statistics/census_tracing.c +++ b/src/core/statistics/census_tracing.c @@ -33,15 +33,154 @@ #include "src/core/statistics/census_interface.h" +#include +#include + +#include "src/core/statistics/census_rpc_stats.h" +#include "src/core/statistics/hash_table.h" +#include +#include +#include +#include +#include +#include + +/* Struct for a trace annotation. */ +typedef struct annotation { + gpr_uint64 ts; /* timestamp of the annotation */ + char txt[CENSUS_MAX_ANNOTATION_LENGTH]; /* actual txt annotation */ + struct annotation* next; +} annotation; + +typedef struct trace_obj { + census_op_id id; + gpr_timespec ts; + census_rpc_stats rpc_stats; + char* method; + annotation* annotations; +} trace_obj; + +static void trace_obj_destroy(trace_obj* obj) { + annotation* p = obj->annotations; + while (p != NULL) { + annotation* next = p->next; + gpr_free(p); + p = next; + } + gpr_free(obj->method); + gpr_free(obj); +} + +static void delete_trace_obj(void* obj) { trace_obj_destroy((trace_obj*)obj); } + +static const census_ht_option ht_opt = { + CENSUS_HT_UINT64 /* key type*/, 571 /* n_of_buckets */, NULL /* hash */, + NULL /* compare_keys */, delete_trace_obj /* delete data */, + NULL /* delete key */}; + +static gpr_once g_init_mutex_once = GPR_ONCE_INIT; +static gpr_mu g_mu; /* Guards following two static variables. */ +static census_ht* g_trace_store = NULL; +static gpr_uint64 g_id = 0; + +static census_ht_key op_id_as_key(census_op_id* id) { + return *(census_ht_key*)id; +} + +static gpr_uint64 op_id_2_uint64(census_op_id* id) { + gpr_uint64 ret; + memcpy(&ret, id, sizeof(census_op_id)); + return ret; +} + +static void init_mutex() { gpr_mu_init(&g_mu); } + +static void init_mutex_once() { gpr_once_init(&g_init_mutex_once, init_mutex); } + census_op_id census_tracing_start_op() { - census_op_id empty_op_id = {0, 0}; - return empty_op_id; + gpr_mu_lock(&g_mu); + { + trace_obj* ret = (trace_obj*)gpr_malloc(sizeof(trace_obj)); + memset(ret, 0, sizeof(trace_obj)); + g_id++; + memcpy(&ret->id, &g_id, sizeof(census_op_id)); + ret->rpc_stats.cnt = 1; + ret->ts = gpr_now(); + census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void*)ret); + gpr_mu_unlock(&g_mu); + gpr_log(GPR_DEBUG, "Start tracing for id %lu\n", g_id); + return ret->id; + } } -int census_add_method_tag(census_op_id op_id, const char* method_name) { - return 0; +int census_add_method_tag(census_op_id op_id, const char* method) { + int ret = 0; + trace_obj* trace = NULL; + gpr_mu_lock(&g_mu); + trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); + if (trace == NULL) { + ret = 1; + } else { + trace->method = gpr_strdup(method); + } + gpr_mu_unlock(&g_mu); + return ret; } void census_tracing_print(census_op_id op_id, const char* annotation) {} -void census_tracing_end_op(census_op_id op_id) {} +void census_tracing_end_op(census_op_id op_id) { + trace_obj* trace = NULL; + gpr_mu_lock(&g_mu); + trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); + if (trace != NULL) { + trace->rpc_stats.elapsed_time_ms = + gpr_timespec_to_micros(gpr_time_sub(gpr_now(), trace->ts)); + gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us\n", + op_id_2_uint64(&op_id), trace->method, + trace->rpc_stats.elapsed_time_ms); + census_ht_erase(g_trace_store, op_id_as_key(&op_id)); + } + gpr_mu_unlock(&g_mu); +} + +void census_tracing_init() { + gpr_log(GPR_INFO, "Initialize census trace store."); + init_mutex_once(); + gpr_mu_lock(&g_mu); + if (g_trace_store == NULL) { + g_id = 1; + g_trace_store = census_ht_create(&ht_opt); + } else { + gpr_log(GPR_ERROR, "Census trace store already initialized."); + } + gpr_mu_unlock(&g_mu); +} + +void census_tracing_shutdown() { + gpr_log(GPR_INFO, "Shutdown census trace store."); + gpr_mu_lock(&g_mu); + if (g_trace_store != NULL) { + census_ht_destroy(g_trace_store); + g_trace_store = NULL; + } else { + gpr_log(GPR_ERROR, "Census trace store is not initialized."); + } + gpr_mu_unlock(&g_mu); +} + +void census_internal_lock_trace_store() { gpr_mu_lock(&g_mu); } + +void census_internal_unlock_trace_store() { gpr_mu_unlock(&g_mu); } + +trace_obj* census_get_trace_obj_locked(census_op_id op_id) { + if (g_trace_store == NULL) { + gpr_log(GPR_ERROR, "Census trace store is not initialized."); + return NULL; + } + return (trace_obj*)census_ht_find(g_trace_store, op_id_as_key(&op_id)); +} + +const char* census_get_trace_method_name(const trace_obj* trace) { + return (const char*)trace->method; +} diff --git a/src/core/statistics/census_tracing.h b/src/core/statistics/census_tracing.h new file mode 100644 index 00000000000..2285a5cd6bd --- /dev/null +++ b/src/core/statistics/census_tracing.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GRPC_INTERNAL_STATISTICS_CENSUS_TRACING_H_ +#define __GRPC_INTERNAL_STATISTICS_CENSUS_TRACING_H_ + +/* Opaque structure for trace object */ +typedef struct trace_obj trace_obj; + +/* Initializes trace store. This function is thread safe. */ +void census_tracing_init(); + +/* Shutsdown trace store. This function is thread safe. */ +void census_tracing_shutdown(); + +/* Gets trace obj corresponding to the input op_id. Returns NULL if trace store + is not initialized or trace obj is not found. Requires trace store being + locked before calling this function. */ +trace_obj* census_get_trace_obj_locked(census_op_id op_id); + +/* The following two functions acquire and release the trace store global lock. + They are for census internal use only. */ +void census_internal_lock_trace_store(); +void census_internal_unlock_trace_store(); + +/* Gets method tag name associated with the input trace object. */ +const char* census_get_trace_method_name(const trace_obj* trace); + +#endif /* __GRPC_INTERNAL_STATISTICS_CENSUS_TRACING_H_ */ diff --git a/src/core/support/time.c b/src/core/support/time.c index 5330092f56b..0e88c65be0c 100644 --- a/src/core/support/time.c +++ b/src/core/support/time.c @@ -264,3 +264,7 @@ gpr_int32 gpr_time_to_millis(gpr_timespec t) { return t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS; } } + +double gpr_timespec_to_micros(gpr_timespec t) { + return t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3; +} diff --git a/test/core/end2end/gen_build_json.py b/test/core/end2end/gen_build_json.py index 6495d6e17e8..50ae21ce692 100755 --- a/test/core/end2end/gen_build_json.py +++ b/test/core/end2end/gen_build_json.py @@ -21,6 +21,7 @@ END2END_TESTS = [ 'cancel_after_invoke', 'cancel_before_invoke', 'cancel_in_a_vacuum', + 'census_simple_request', 'disappearing_server', 'early_server_shutdown_finishes_inflight_calls', 'early_server_shutdown_finishes_tags', diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c new file mode 100644 index 00000000000..64c0d12ca4a --- /dev/null +++ b/test/core/end2end/tests/census_simple_request.c @@ -0,0 +1,176 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static gpr_timespec n_seconds_time(int n) { + return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n)); +} + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_client(&f, client_args); + config.init_server(&f, server_args); + return f; +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown(f->server); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event *ev; + grpc_completion_type type; + do { + ev = grpc_completion_queue_next(cq, n_seconds_time(5)); + GPR_ASSERT(ev); + type = ev->type; + grpc_event_finish(ev); + } while (type != GRPC_QUEUE_SHUTDOWN); +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->server_cq); + drain_cq(f->server_cq); + grpc_completion_queue_destroy(f->server_cq); + grpc_completion_queue_shutdown(f->client_cq); + drain_cq(f->client_cq); + grpc_completion_queue_destroy(f->client_cq); +} + +static void *tag(gpr_intptr t) { return (void *)t; } + +static void test_body(grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + gpr_timespec deadline = n_seconds_time(10); + cq_verifier *v_client = cq_verifier_create(f.client_cq); + cq_verifier *v_server = cq_verifier_create(f.server_cq); + + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + GPR_ASSERT(c); + tag(1); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_start_invoke(c, f.client_cq, tag(1), tag(2), tag(3), 0)); + cq_expect_invoke_accepted(v_client, tag(1), GRPC_OP_OK); + cq_verify(v_client); + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); + cq_verify(v_client); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", + deadline, NULL); + cq_verify(v_server); + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_accept(s, f.server_cq, tag(102), 0)); + cq_expect_client_metadata_read(v_client, tag(2), NULL); + cq_verify(v_client); + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); + cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, + "xyz", NULL); + cq_verify(v_client); + + cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); + cq_verify(v_server); + cq_expect_finished(v_server, tag(102), NULL); + cq_verify(v_server); + grpc_call_destroy(c); + grpc_call_destroy(s); + + cq_verifier_destroy(v_client); + cq_verifier_destroy(v_server); +} + +static void test_invoke_request_with_census( + grpc_end2end_test_config config, const char *name, + void (*body)(grpc_end2end_test_fixture f)) { + char fullname[64]; + grpc_end2end_test_fixture f; + grpc_arg client_arg, server_arg; + grpc_channel_args client_args, server_args; + + client_arg.type = GRPC_ARG_INTEGER; + client_arg.key = GRPC_ARG_ENABLE_CENSUS; + client_arg.value.integer = 1; + + client_args.num_args = 1; + client_args.args = &client_arg; + + server_arg.type = GRPC_ARG_INTEGER; + server_arg.key = GRPC_ARG_ENABLE_CENSUS; + server_arg.value.integer = 1; + server_args.num_args = 1; + server_args.args = &server_arg; + + sprintf(fullname, "%s/%s", __FUNCTION__, name); + f = begin_test(config, fullname, &client_args, &server_args); + body(f); + end_test(&f); + config.tear_down_data(&f); +} + +void grpc_end2end_tests(grpc_end2end_test_config config) { + test_invoke_request_with_census(config, "census_simple_request", test_body); +} diff --git a/test/core/statistics/census_stub_test.c b/test/core/statistics/census_stub_test.c index 7d85550f701..a86676fbb1b 100644 --- a/test/core/statistics/census_stub_test.c +++ b/test/core/statistics/census_stub_test.c @@ -44,7 +44,8 @@ void test_census_stubs() { census_op_id op_id; census_rpc_stats* stats = census_rpc_stats_create_empty(); - census_aggregated_rpc_stats data_map; + census_aggregated_rpc_stats data_map = {0, NULL}; + /* Initializes census library at server start up time. */ census_init(); /* Starts tracing at the beginning of a rpc. */ @@ -62,8 +63,9 @@ void test_census_stubs() { census_tracing_end_op(op_id); /* In process stats queries. */ census_get_server_stats(&data_map); + census_aggregated_rpc_stats_set_empty(&data_map); census_get_client_stats(&data_map); - census_aggregated_rpc_stats_destroy(&data_map); + census_aggregated_rpc_stats_set_empty(&data_map); gpr_free(stats); census_shutdown(); } diff --git a/test/core/statistics/rpc_stats_test.c b/test/core/statistics/rpc_stats_test.c new file mode 100644 index 00000000000..c1014034500 --- /dev/null +++ b/test/core/statistics/rpc_stats_test.c @@ -0,0 +1,197 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/core/statistics/census_interface.h" +#include "src/core/statistics/census_rpc_stats.h" +#include "src/core/statistics/census_tracing.h" +#include +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +/* Ensure all possible state transitions are called without causing problem */ +static void test_init_shutdown() { + census_stats_store_init(); + census_stats_store_init(); + census_stats_store_shutdown(); + census_stats_store_shutdown(); + census_stats_store_init(); +} + +static void test_create_and_destroy() { + census_rpc_stats* stats = NULL; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + stats = census_rpc_stats_create_empty(); + GPR_ASSERT(stats != NULL); + GPR_ASSERT(stats->cnt == 0 && stats->rpc_error_cnt == 0 && + stats->app_error_cnt == 0 && stats->elapsed_time_ms == 0.0 && + stats->api_request_bytes == 0 && stats->wire_request_bytes == 0 && + stats->api_response_bytes == 0 && stats->wire_response_bytes == 0); + gpr_free(stats); + + census_aggregated_rpc_stats_set_empty(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + agg_stats.num_entries = 1; + agg_stats.stats = (census_per_method_rpc_stats*)gpr_malloc( + sizeof(census_per_method_rpc_stats)); + agg_stats.stats[0].method = gpr_strdup("foo"); + census_aggregated_rpc_stats_set_empty(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); +} + +#define ASSERT_NEAR(a, b) \ + GPR_ASSERT((a - b) * (a - b) < 1e-24 * (a + b) * (a + b)) + +static void test_record_and_get_stats() { + census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; + census_op_id id; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + /* Record client stats twice with the same op_id. */ + census_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, "m1"); + census_record_rpc_client_stats(id, &stats); + census_record_rpc_client_stats(id, &stats); + census_tracing_end_op(id); + /* Server stats expect to be empty */ + census_get_server_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + /* Client stats expect to have one entry */ + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 1); + GPR_ASSERT(agg_stats.stats != NULL); + GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m1") == 0); + GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 2 && + agg_stats.stats[0].hour_stats.cnt == 2 && + agg_stats.stats[0].total_stats.cnt == 2); + ASSERT_NEAR(agg_stats.stats[0].minute_stats.wire_response_bytes, 16.8); + ASSERT_NEAR(agg_stats.stats[0].hour_stats.wire_response_bytes, 16.8); + ASSERT_NEAR(agg_stats.stats[0].total_stats.wire_response_bytes, 16.8); + /* Get stats again, results should be the same. */ + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 1); + census_aggregated_rpc_stats_set_empty(&agg_stats); + census_shutdown(); + + /* Record both server (once) and client (twice) stats with different op_ids.*/ + census_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, "m2"); + census_record_rpc_client_stats(id, &stats); + census_tracing_end_op(id); + id = census_tracing_start_op(); + census_add_method_tag(id, "m3"); + census_record_rpc_server_stats(id, &stats); + census_tracing_end_op(id); + id = census_tracing_start_op(); + census_add_method_tag(id, "m4"); + census_record_rpc_client_stats(id, &stats); + census_tracing_end_op(id); + /* Check server stats */ + census_get_server_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 1); + GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m3") == 0); + GPR_ASSERT(agg_stats.stats[0].minute_stats.app_error_cnt == 3 && + agg_stats.stats[0].hour_stats.app_error_cnt == 3 && + agg_stats.stats[0].total_stats.app_error_cnt == 3); + census_aggregated_rpc_stats_set_empty(&agg_stats); + /* Check client stats */ + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 2); + GPR_ASSERT(agg_stats.stats != NULL); + GPR_ASSERT((strcmp(agg_stats.stats[0].method, "m2") == 0 && + strcmp(agg_stats.stats[1].method, "m4") == 0) || + (strcmp(agg_stats.stats[0].method, "m4") == 0 && + strcmp(agg_stats.stats[1].method, "m2") == 0)); + GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 1 && + agg_stats.stats[1].minute_stats.cnt == 1); + census_aggregated_rpc_stats_set_empty(&agg_stats); + census_shutdown(); +} + +static void test_record_stats_on_unknown_op_id() { + census_op_id unknown_id = {0xDEAD, 0xBEEF}; + census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + census_init(); + /* Tests that recording stats against unknown id is noop. */ + census_record_rpc_client_stats(unknown_id, &stats); + census_record_rpc_server_stats(unknown_id, &stats); + census_get_server_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + GPR_ASSERT(agg_stats.stats == NULL); + census_aggregated_rpc_stats_set_empty(&agg_stats); + census_shutdown(); +} + +/* Test that record stats is noop when trace store is uninitialized. */ +static void test_record_stats_with_trace_store_uninitialized() { + census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4}; + census_op_id id = {0, 0}; + census_aggregated_rpc_stats agg_stats = {0, NULL}; + + census_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, "m"); + census_tracing_end_op(id); + /* shuts down trace store only. */ + census_tracing_shutdown(); + census_record_rpc_client_stats(id, &stats); + census_get_client_stats(&agg_stats); + GPR_ASSERT(agg_stats.num_entries == 0); + census_stats_store_shutdown(); +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + test_init_shutdown(); + test_create_and_destroy(); + test_record_and_get_stats(); + test_record_stats_on_unknown_op_id(); + test_record_stats_with_trace_store_uninitialized(); + return 0; +} diff --git a/test/core/statistics/trace_test.c b/test/core/statistics/trace_test.c new file mode 100644 index 00000000000..d1f384e20f4 --- /dev/null +++ b/test/core/statistics/trace_test.c @@ -0,0 +1,158 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/core/statistics/census_interface.h" +#include "src/core/statistics/census_tracing.h" +#include "src/core/statistics/census_tracing.h" +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +/* Ensure all possible state transitions are called without causing problem */ +static void test_init_shutdown() { + census_tracing_init(); + census_tracing_init(); + census_tracing_shutdown(); + census_tracing_shutdown(); + census_tracing_init(); +} + +static void test_start_op_generates_locally_unique_ids() { +/* Check that ids generated within window size of 1000 are unique. + TODO(hongyu): Replace O(n^2) duplicate detection algorithm with O(nlogn) + algorithm. Enhance the test to larger window size (>10^6) */ +#define WINDOW_SIZE 1000 + census_op_id ids[WINDOW_SIZE]; + int i; + census_init(); + for (i = 0; i < WINDOW_SIZE; i++) { + ids[i] = census_tracing_start_op(); + census_tracing_end_op(ids[i]); + } + for (i = 0; i < WINDOW_SIZE - 1; i++) { + int j; + for (j = i + 1; j < WINDOW_SIZE; j++) { + GPR_ASSERT(ids[i].upper != ids[j].upper || ids[i].lower != ids[j].lower); + } + } +#undef WINDOW_SIZE + census_shutdown(); +} + +static void test_get_trace_method_name() { + census_op_id id; + const char write_name[] = "service/method"; + census_tracing_init(); + id = census_tracing_start_op(); + census_add_method_tag(id, write_name); + census_internal_lock_trace_store(); + { + const char* read_name = + census_get_trace_method_name(census_get_trace_obj_locked(id)); + GPR_ASSERT(strcmp(read_name, write_name) == 0); + } + census_internal_unlock_trace_store(); + census_tracing_shutdown(); +} + +typedef struct thd_arg { + int num_done; + gpr_cv done; + gpr_mu mu; +} thd_arg; + +static void mimic_trace_op_sequences(void* arg) { + census_op_id id; + char method_name[200]; + int i = 0; + const int num_iter = 200; + thd_arg* args = (thd_arg*)arg; + GPR_ASSERT(args != NULL); + gpr_log(GPR_INFO, "Start trace op sequence thread."); + for (i = 0; i < num_iter; i++) { + id = census_tracing_start_op(); + census_add_method_tag(id, method_name); + /* pretend doing 1us work. */ + gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_micros(1))); + census_tracing_end_op(id); + } + gpr_log(GPR_INFO, "End trace op sequence thread."); + gpr_mu_lock(&args->mu); + args->num_done += 1; + gpr_cv_broadcast(&args->done); + gpr_mu_unlock(&args->mu); +} + +static void test_concurrency() { +#define NUM_THREADS 1000 + gpr_thd_id tid[NUM_THREADS]; + int i = 0; + thd_arg arg; + arg.num_done = 0; + gpr_mu_init(&arg.mu); + gpr_cv_init(&arg.done); + census_tracing_init(); + for (i = 0; i < NUM_THREADS; ++i) { + gpr_thd_new(tid + i, mimic_trace_op_sequences, &arg, NULL); + } + while (arg.num_done < NUM_THREADS) { + gpr_log(GPR_INFO, "num done %d", arg.num_done); + gpr_cv_wait(&arg.done, &arg.mu, gpr_inf_future); + } + census_tracing_shutdown(); +#undef NUM_THREADS +} + +static void test_add_method_tag_to_unknown_op_id() { + census_op_id unknown_id = {0xDEAD, 0xBEEF}; + int ret = 0; + census_tracing_init(); + ret = census_add_method_tag(unknown_id, "foo"); + GPR_ASSERT(ret != 0); + census_tracing_shutdown(); +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + test_init_shutdown(); + test_start_op_generates_locally_unique_ids(); + test_get_trace_method_name(); + test_concurrency(); + test_add_method_tag_to_unknown_op_id(); + return 0; +} diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index 6cc5a8b2932..294b73f155e 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -134,6 +134,7 @@ + diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj index 6cc5a8b2932..294b73f155e 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj @@ -134,6 +134,7 @@ + From 1456d1522172e558b7c826b4d4b0977b67f43e82 Mon Sep 17 00:00:00 2001 From: yangg Date: Thu, 8 Jan 2015 15:39:58 -0800 Subject: [PATCH 11/29] Add a test to export two TestService on the same server, only with different package names. Make sure they work as intended. This is based on [] Change on 2015/01/08 by yangg ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83558743 --- Makefile | 24 ++++- build.json | 3 + test/cpp/end2end/end2end_test.cc | 143 ++++++++++++++++------------- test/cpp/util/echo.proto | 20 +--- test/cpp/util/echo_duplicate.proto | 12 +++ test/cpp/util/messages.proto | 21 +++++ 6 files changed, 138 insertions(+), 85 deletions(-) create mode 100644 test/cpp/util/echo_duplicate.proto create mode 100644 test/cpp/util/messages.proto diff --git a/Makefile b/Makefile index 153d0924efa..8be41960452 100644 --- a/Makefile +++ b/Makefile @@ -965,6 +965,24 @@ gens/test/cpp/util/echo.pb.cc: test/cpp/util/echo.proto protoc_plugins $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) --cpp_out=gens --grpc_out=gens --plugin=protoc-gen-grpc=bins/$(CONFIG)/cpp_plugin $< +deps/$(CONFIG)/gens/test/cpp/util/echo_duplicate.pb.dep: + $(Q) mkdir -p `dirname $@` + $(Q) touch $@ + +gens/test/cpp/util/echo_duplicate.pb.cc: test/cpp/util/echo_duplicate.proto protoc_plugins + $(E) "[PROTOC] Generating protobuf CC file from $<" + $(Q) mkdir -p `dirname $@` + $(Q) $(PROTOC) --cpp_out=gens --grpc_out=gens --plugin=protoc-gen-grpc=bins/$(CONFIG)/cpp_plugin $< + +deps/$(CONFIG)/gens/test/cpp/util/messages.pb.dep: + $(Q) mkdir -p `dirname $@` + $(Q) touch $@ + +gens/test/cpp/util/messages.pb.cc: test/cpp/util/messages.proto protoc_plugins + $(E) "[PROTOC] Generating protobuf CC file from $<" + $(Q) mkdir -p `dirname $@` + $(Q) $(PROTOC) --cpp_out=gens --grpc_out=gens --plugin=protoc-gen-grpc=bins/$(CONFIG)/cpp_plugin $< + deps/$(CONFIG)/%.dep : %.c $(E) "[DEP] Generating dependencies for $<" @@ -1643,7 +1661,9 @@ clean_libgrpc++: LIBGRPC++_TEST_UTIL_SRC = \ + gens/test/cpp/util/messages.pb.cc \ gens/test/cpp/util/echo.pb.cc \ + gens/test/cpp/util/echo_duplicate.pb.cc \ test/cpp/util/create_test_channel.cc \ test/cpp/end2end/async_test_server.cc \ @@ -5199,10 +5219,10 @@ bins/$(CONFIG)/end2end_test: openssl_dep_error else -bins/$(CONFIG)/end2end_test: $(END2END_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a +bins/$(CONFIG)/end2end_test: $(END2END_TEST_OBJS) libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(END2END_TEST_OBJS) $(GTEST_LIB) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/end2end_test + $(Q) $(LDXX) $(LDFLAGS) $(END2END_TEST_OBJS) $(GTEST_LIB) libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/end2end_test endif diff --git a/build.json b/build.json index d60f4e5705c..25415720a55 100644 --- a/build.json +++ b/build.json @@ -386,7 +386,9 @@ "name": "grpc++_test_util", "build": "test", "src": [ + "test/cpp/util/messages.proto", "test/cpp/util/echo.proto", + "test/cpp/util/echo_duplicate.proto", "test/cpp/util/create_test_channel.cc", "test/cpp/end2end/async_test_server.cc" ], @@ -1348,6 +1350,7 @@ "test/cpp/end2end/end2end_test.cc" ], "deps": [ + "grpc++_test_util", "grpc_test_util", "grpc++", "grpc", diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 83037b5ab18..f63f6ad0763 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -34,6 +34,7 @@ #include #include +#include "net/grpc/cpp/echo_duplicate_proto_cc.pb.h" #include "test/cpp/util/echo.pb.h" #include "src/cpp/server/rpc_service_method.h" #include "src/cpp/util/time.h" @@ -55,7 +56,6 @@ using grpc::cpp::test::util::EchoRequest; using grpc::cpp::test::util::EchoResponse; -using grpc::cpp::test::util::TestService; using std::chrono::system_clock; namespace grpc { @@ -77,10 +77,10 @@ void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request, } } // namespace -class TestServiceImpl : public TestService::Service { +class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service { public: Status Echo(ServerContext* context, const EchoRequest* request, - EchoResponse* response) { + EchoResponse* response) override { response->set_message(request->message()); MaybeEchoDeadline(context, request, response); return Status::OK; @@ -90,7 +90,7 @@ class TestServiceImpl : public TestService::Service { Status RequestStream(ServerContext* context, ServerReader* reader, - EchoResponse* response) { + EchoResponse* response) override { EchoRequest request; response->set_message(""); while (reader->Read(&request)) { @@ -102,7 +102,7 @@ class TestServiceImpl : public TestService::Service { // Return 3 messages. // TODO(yangg) make it generic by adding a parameter into EchoRequest Status ResponseStream(ServerContext* context, const EchoRequest* request, - ServerWriter* writer) { + ServerWriter* writer) override { EchoResponse response; response.set_message(request->message() + "0"); writer->Write(response); @@ -114,8 +114,9 @@ class TestServiceImpl : public TestService::Service { return Status::OK; } - Status BidiStream(ServerContext* context, - ServerReaderWriter* stream) { + Status BidiStream( + ServerContext* context, + ServerReaderWriter* stream) override { EchoRequest request; EchoResponse response; while (stream->Read(&request)) { @@ -127,6 +128,16 @@ class TestServiceImpl : public TestService::Service { } }; +class TestServiceImplDupPkg + : public ::grpc::cpp::test::util::duplicate::TestService::Service { + public: + Status Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response) override { + response->set_message("no package"); + return Status::OK; + } +}; + class End2endTest : public ::testing::Test { protected: void SetUp() override { @@ -136,6 +147,7 @@ class End2endTest : public ::testing::Test { ServerBuilder builder; builder.AddPort(server_address_.str()); builder.RegisterService(service_.service()); + builder.RegisterService(dup_pkg_service_.service()); server_ = builder.BuildAndStart(); } @@ -143,15 +155,21 @@ class End2endTest : public ::testing::Test { server_->Shutdown(); } + void ResetStub() { + std::shared_ptr channel = + CreateChannel(server_address_.str(), ChannelArguments()); + stub_.reset(grpc::cpp::test::util::TestService::NewStub(channel)); + } + + std::unique_ptr stub_; std::unique_ptr server_; std::ostringstream server_address_; TestServiceImpl service_; + TestServiceImplDupPkg dup_pkg_service_; }; -static void SendRpc(const grpc::string& server_address, int num_rpcs) { - std::shared_ptr channel = - CreateChannel(server_address, ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); +static void SendRpc(grpc::cpp::test::util::TestService::Stub* stub, + int num_rpcs) { EchoRequest request; EchoResponse response; request.set_message("Hello"); @@ -162,18 +180,18 @@ static void SendRpc(const grpc::string& server_address, int num_rpcs) { EXPECT_EQ(response.message(), request.message()); EXPECT_TRUE(s.IsOk()); } - - delete stub; } TEST_F(End2endTest, SimpleRpc) { - SendRpc(server_address_.str(), 1); + ResetStub(); + SendRpc(stub_.get(), 1); } TEST_F(End2endTest, MultipleRpcs) { + ResetStub(); vector threads; for (int i = 0; i < 10; ++i) { - threads.push_back(new std::thread(SendRpc, server_address_.str(), 10)); + threads.push_back(new std::thread(SendRpc, stub_.get(), 10)); } for (int i = 0; i < 10; ++i) { threads[i]->join(); @@ -183,9 +201,7 @@ TEST_F(End2endTest, MultipleRpcs) { // Set a 10us deadline and make sure proper error is returned. TEST_F(End2endTest, RpcDeadlineExpires) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; request.set_message("Hello"); @@ -194,19 +210,15 @@ TEST_F(End2endTest, RpcDeadlineExpires) { std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + std::chrono::microseconds(10); context.set_absolute_deadline(deadline); - Status s = stub->Echo(&context, request, &response); + Status s = stub_->Echo(&context, request, &response); // TODO(yangg) use correct error code when b/18793983 is fixed. // EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, s.code()); EXPECT_EQ(StatusCode::CANCELLED, s.code()); - - delete stub; } // Set a long but finite deadline. TEST_F(End2endTest, RpcLongDeadline) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; request.set_message("Hello"); @@ -215,18 +227,14 @@ TEST_F(End2endTest, RpcLongDeadline) { std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + std::chrono::hours(1); context.set_absolute_deadline(deadline); - Status s = stub->Echo(&context, request, &response); + Status s = stub_->Echo(&context, request, &response); EXPECT_EQ(response.message(), request.message()); EXPECT_TRUE(s.IsOk()); - - delete stub; } // Ask server to echo back the deadline it sees. TEST_F(End2endTest, EchoDeadline) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; request.set_message("Hello"); @@ -236,7 +244,7 @@ TEST_F(End2endTest, EchoDeadline) { std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + std::chrono::seconds(100); context.set_absolute_deadline(deadline); - Status s = stub->Echo(&context, request, &response); + Status s = stub_->Echo(&context, request, &response); EXPECT_EQ(response.message(), request.message()); EXPECT_TRUE(s.IsOk()); gpr_timespec sent_deadline; @@ -244,56 +252,44 @@ TEST_F(End2endTest, EchoDeadline) { // Allow 1 second error. EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 1); EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1); - - delete stub; } // Ask server to echo back the deadline it sees. The rpc has no deadline. TEST_F(End2endTest, EchoDeadlineForNoDeadlineRpc) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; request.set_message("Hello"); request.mutable_param()->set_echo_deadline(true); ClientContext context; - Status s = stub->Echo(&context, request, &response); + Status s = stub_->Echo(&context, request, &response); EXPECT_EQ(response.message(), request.message()); EXPECT_TRUE(s.IsOk()); EXPECT_EQ(response.param().request_deadline(), gpr_inf_future.tv_sec); - - delete stub; } TEST_F(End2endTest, UnimplementedRpc) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; request.set_message("Hello"); ClientContext context; - Status s = stub->Unimplemented(&context, request, &response); + Status s = stub_->Unimplemented(&context, request, &response); EXPECT_FALSE(s.IsOk()); EXPECT_EQ(s.code(), grpc::StatusCode::UNIMPLEMENTED); EXPECT_EQ(s.details(), ""); EXPECT_EQ(response.message(), ""); - - delete stub; } TEST_F(End2endTest, RequestStreamOneRequest) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; ClientContext context; - ClientWriter* stream = stub->RequestStream(&context, &response); + ClientWriter* stream = stub_->RequestStream(&context, &response); request.set_message("hello"); EXPECT_TRUE(stream->Write(request)); stream->WritesDone(); @@ -302,18 +298,15 @@ TEST_F(End2endTest, RequestStreamOneRequest) { EXPECT_TRUE(s.IsOk()); delete stream; - delete stub; } TEST_F(End2endTest, RequestStreamTwoRequests) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; ClientContext context; - ClientWriter* stream = stub->RequestStream(&context, &response); + ClientWriter* stream = stub_->RequestStream(&context, &response); request.set_message("hello"); EXPECT_TRUE(stream->Write(request)); EXPECT_TRUE(stream->Write(request)); @@ -323,19 +316,17 @@ TEST_F(End2endTest, RequestStreamTwoRequests) { EXPECT_TRUE(s.IsOk()); delete stream; - delete stub; } TEST_F(End2endTest, ResponseStream) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; ClientContext context; request.set_message("hello"); - ClientReader* stream = stub->ResponseStream(&context, &request); + ClientReader* stream = + stub_->ResponseStream(&context, &request); EXPECT_TRUE(stream->Read(&response)); EXPECT_EQ(response.message(), request.message() + "0"); EXPECT_TRUE(stream->Read(&response)); @@ -348,20 +339,17 @@ TEST_F(End2endTest, ResponseStream) { EXPECT_TRUE(s.IsOk()); delete stream; - delete stub; } TEST_F(End2endTest, BidiStream) { - std::shared_ptr channel = - CreateChannel(server_address_.str(), ChannelArguments()); - TestService::Stub* stub = TestService::NewStub(channel); + ResetStub(); EchoRequest request; EchoResponse response; ClientContext context; grpc::string msg("hello"); ClientReaderWriter* stream = - stub->BidiStream(&context); + stub_->BidiStream(&context); request.set_message(msg + "0"); EXPECT_TRUE(stream->Write(request)); @@ -385,7 +373,32 @@ TEST_F(End2endTest, BidiStream) { EXPECT_TRUE(s.IsOk()); delete stream; - delete stub; +} + +// Talk to the two services with the same name but different package names. +// The two stubs are created on the same channel. +TEST_F(End2endTest, DiffPackageServices) { + std::shared_ptr channel = + CreateChannel(server_address_.str(), ChannelArguments()); + + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + std::unique_ptr stub( + grpc::cpp::test::util::TestService::NewStub(channel)); + ClientContext context; + Status s = stub->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.IsOk()); + + std::unique_ptr + dup_pkg_stub( + grpc::cpp::test::util::duplicate::TestService::NewStub(channel)); + ClientContext context2; + s = dup_pkg_stub->Echo(&context2, request, &response); + EXPECT_EQ("no package", response.message()); + EXPECT_TRUE(s.IsOk()); } } // namespace testing diff --git a/test/cpp/util/echo.proto b/test/cpp/util/echo.proto index 1240399bf88..bd5357fe197 100644 --- a/test/cpp/util/echo.proto +++ b/test/cpp/util/echo.proto @@ -1,24 +1,8 @@ syntax = "proto2"; -package grpc.cpp.test.util; - -message RequestParams { - optional bool echo_deadline = 1; -} - -message EchoRequest { - optional string message = 1; - optional RequestParams param = 2; -} +import "test/cpp/util/messages.proto"; -message ResponseParams { - optional int64 request_deadline = 1; -} - -message EchoResponse { - optional string message = 1; - optional ResponseParams param = 2; -} +package grpc.cpp.test.util; service TestService { rpc Echo(EchoRequest) returns (EchoResponse); diff --git a/test/cpp/util/echo_duplicate.proto b/test/cpp/util/echo_duplicate.proto new file mode 100644 index 00000000000..c9266833e22 --- /dev/null +++ b/test/cpp/util/echo_duplicate.proto @@ -0,0 +1,12 @@ +// This is a partial copy of echo.proto with a different package name. + +syntax = "proto2"; + +import "test/cpp/util/messages.proto"; + +package grpc.cpp.test.util.duplicate; + +service TestService { + rpc Echo(grpc.cpp.test.util.EchoRequest) + returns (grpc.cpp.test.util.EchoResponse); +} diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto new file mode 100644 index 00000000000..d541821b655 --- /dev/null +++ b/test/cpp/util/messages.proto @@ -0,0 +1,21 @@ +syntax = "proto2"; + +package grpc.cpp.test.util; + +message RequestParams { + optional bool echo_deadline = 1; +} + +message EchoRequest { + optional string message = 1; + optional RequestParams param = 2; +} + +message ResponseParams { + optional int64 request_deadline = 1; +} + +message EchoResponse { + optional string message = 1; + optional ResponseParams param = 2; +} From 8bf337bedfd35bd6ace0882ae2ea703926dfc8df Mon Sep 17 00:00:00 2001 From: ctiller Date: Fri, 9 Jan 2015 08:59:08 -0800 Subject: [PATCH 12/29] Fix test under msan Change on 2015/01/09 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83609353 --- test/core/statistics/trace_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/statistics/trace_test.c b/test/core/statistics/trace_test.c index d1f384e20f4..b06fbd574b2 100644 --- a/test/core/statistics/trace_test.c +++ b/test/core/statistics/trace_test.c @@ -98,7 +98,7 @@ typedef struct thd_arg { static void mimic_trace_op_sequences(void* arg) { census_op_id id; - char method_name[200]; + const char* method_name = "service_foo/method_bar"; int i = 0; const int num_iter = 200; thd_arg* args = (thd_arg*)arg; From a5cf7bd7e6750ba3d8ed89a22466997adfbf7e6a Mon Sep 17 00:00:00 2001 From: ctiller Date: Fri, 9 Jan 2015 09:15:02 -0800 Subject: [PATCH 13/29] Remove mutex as this process is now single threaded Change on 2015/01/09 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83610407 --- tools/run_tests/watch_dirs.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/tools/run_tests/watch_dirs.py b/tools/run_tests/watch_dirs.py index 8ebbb271806..056e69a16c4 100755 --- a/tools/run_tests/watch_dirs.py +++ b/tools/run_tests/watch_dirs.py @@ -1,7 +1,6 @@ """Helper to watch a (set) of directories for modifications.""" import os -import threading import time @@ -11,7 +10,6 @@ class DirWatcher(object): def __init__(self, paths): if isinstance(paths, basestring): paths = [paths] - self._mu = threading.Lock() self._done = False self.paths = list(paths) self.lastrun = time.time() @@ -35,12 +33,8 @@ class DirWatcher(object): return most_recent_change def most_recent_change(self): - self._mu.acquire() - try: - if time.time() - self.lastrun > 1: - self._cache = self._calculate() - self.lastrun = time.time() - return self._cache - finally: - self._mu.release() + if time.time() - self.lastrun > 1: + self._cache = self._calculate() + self.lastrun = time.time() + return self._cache From 94e5ddece6355939764bab6c2142d07b85f246ac Mon Sep 17 00:00:00 2001 From: ctiller Date: Fri, 9 Jan 2015 10:41:59 -0800 Subject: [PATCH 14/29] Only run one make at a time. If openssl has not been built, running parallel make processes causes some problems. Change on 2015/01/09 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83617340 --- tools/run_tests/jobset.py | 13 +++++++------ tools/run_tests/run_tests.py | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py index d3a46b63e14..2ab95ef97c7 100755 --- a/tools/run_tests/jobset.py +++ b/tools/run_tests/jobset.py @@ -8,7 +8,7 @@ import tempfile import time -_MAX_JOBS = 16 * multiprocessing.cpu_count() +_DEFAULT_MAX_JOBS = 16 * multiprocessing.cpu_count() def shuffle_iteratable(it): @@ -81,15 +81,16 @@ class Job(object): class Jobset(object): """Manages one run of jobs.""" - def __init__(self, check_cancelled): + def __init__(self, check_cancelled, maxjobs): self._running = set() self._check_cancelled = check_cancelled self._cancelled = False self._failures = 0 + self._maxjobs = maxjobs def start(self, cmdline): """Start a job. Return True on success, False on failure.""" - while len(self._running) >= _MAX_JOBS: + while len(self._running) >= self._maxjobs: if self.cancelled(): return False self.reap() if self.cancelled(): return False @@ -130,10 +131,10 @@ def _never_cancelled(): return False -def run(cmdlines, check_cancelled=_never_cancelled): - js = Jobset(check_cancelled) +def run(cmdlines, check_cancelled=_never_cancelled, maxjobs=None): + js = Jobset(check_cancelled, + maxjobs if maxjobs is not None else _DEFAULT_MAX_JOBS) for cmdline in shuffle_iteratable(cmdlines): if not js.start(cmdline): break return js.finish() - diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 9234682bea7..d678721274f 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -43,10 +43,10 @@ def _build_and_run(check_cancelled): # build latest, sharing cpu between the various makes if not jobset.run( (['make', - '-j', '%d' % max(multiprocessing.cpu_count() / len(configs), 1), + '-j', '%d' % (multiprocessing.cpu_count() + 1), 'buildtests_c', 'CONFIG=%s' % cfg] - for cfg in configs), check_cancelled): + for cfg in configs), check_cancelled, maxjobs=1): sys.exit(1) # run all the tests From 68481413872341dd78d16217145a9469a7faaeb0 Mon Sep 17 00:00:00 2001 From: zhangkun Date: Fri, 9 Jan 2015 11:03:17 -0800 Subject: [PATCH 15/29] Remove dependencies on internal headers from Java gRPC compiler plugin. Instead, use functions from names.h which is going to be exported in the opensource protobuf. Also tailor includes to work with the current MOE configuration. Change on 2015/01/09 by zhangkun ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83619218 --- src/compiler/java_generator.cc | 701 +++++++++++++++++++++++++++++++++ src/compiler/java_generator.h | 55 +++ src/compiler/java_plugin.cc | 84 ++++ 3 files changed, 840 insertions(+) create mode 100644 src/compiler/java_generator.cc create mode 100644 src/compiler/java_generator.h create mode 100644 src/compiler/java_plugin.cc diff --git a/src/compiler/java_generator.cc b/src/compiler/java_generator.cc new file mode 100644 index 00000000000..6915bbfcb20 --- /dev/null +++ b/src/compiler/java_generator.cc @@ -0,0 +1,701 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/compiler/java_generator.h" + +#include +#include "net/proto2/compiler/java/public/names.h" +#include +#include +#include "net/proto_compiler/proto.h" +#include "net/proto_compiler/proto-inl.h" + +namespace java_grpc_generator { + +using google::protobuf::FileDescriptor; +using google::protobuf::ServiceDescriptor; +using google::protobuf::MethodDescriptor; +using google::protobuf::Descriptor; +using google::protobuf::io::Printer; + +// Adjust a method name prefix identifier to follow the JavaBean spec: +// - decapitalize the first letter +// - remove embedded underscores & capitalize the following letter +static string MixedLower(const string& word) { + string w; + w += tolower(word[0]); + bool after_underscore = false; + for (int i = 1; i < word.length(); ++i) { + if (word[i] == '_') { + after_underscore = true; + } else { + w += after_underscore ? toupper(word[i]) : word[i]; + after_underscore = false; + } + } + return w; +} + +// Converts to the identifier to the ALL_UPPER_CASE format. +// - An underscore is inserted where a lower case letter is followed by an +// upper case letter. +// - All letters are converted to upper case +static string ToAllUpperCase(const string& word) { + string w; + for (int i = 0; i < word.length(); ++i) { + w += toupper(word[i]); + if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) { + w += '_'; + } + } + return w; +} + +static inline string LowerMethodName(const MethodDescriptor* method) { + return MixedLower(method->name()); +} + +static inline string MethodPropertiesFieldName(const MethodDescriptor* method) { + return "METHOD_" + ToAllUpperCase(method->name()); +} + +static inline string MessageFullJavaName(const Descriptor* desc) { + return google::protobuf::compiler::java::ClassName(desc); +} + +static void PrintMethodFields( + const ServiceDescriptor* service, map* vars, Printer* p) { + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["method_name"] = method->name(); + (*vars)["input_type"] = MessageFullJavaName(method->input_type()); + (*vars)["output_type"] = MessageFullJavaName(method->output_type()); + (*vars)["method_field_name"] = MethodPropertiesFieldName(method); + bool client_streaming = method->client_streaming(); + bool server_streaming = method->server_streaming(); + if (client_streaming) { + if (server_streaming) { + (*vars)["method_type"] = "DUPLEX_STREAMING"; + } else { + (*vars)["method_type"] = "CLIENT_STREAMING"; + } + } else { + if (server_streaming) { + (*vars)["method_type"] = "SERVER_STREAMING"; + } else { + (*vars)["method_type"] = "UNARY"; + } + } + p->Print( + *vars, + "private static final $Method$<$input_type$,\n" + " $output_type$> $method_field_name$ =\n" + " $Method$.create(\n" + " $MethodType$.$method_type$, \"$method_name$\",\n" + " $ProtoUtils$.marshaller($input_type$.PARSER),\n" + " $ProtoUtils$.marshaller($output_type$.PARSER));\n"); + } + p->Print("\n"); +} + +static void PrintServiceDescriptor( + const ServiceDescriptor* service, map* vars, Printer* p) { + (*vars)["service_name"] = service->name(); + p->Print( + *vars, + "@$Immutable$\n"); + p->Print( + *vars, + "public static class $service_name$ServiceDescriptor extends\n" + " $AbstractServiceDescriptor$<$service_name$ServiceDescriptor> {\n"); + p->Indent(); + + // Service descriptor fields + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["input_type"] = MessageFullJavaName(method->input_type()); + (*vars)["output_type"] = MessageFullJavaName(method->output_type()); + (*vars)["lower_method_name"] = LowerMethodName(method); + p->Print( + *vars, + "public final $MethodDescriptor$<$input_type$,\n" + " $output_type$> $lower_method_name$;\n"); + } + + // The default constructor + p->Print( + *vars, + "\nprivate $service_name$ServiceDescriptor() {\n"); + p->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["method_field_name"] = MethodPropertiesFieldName(method); + (*vars)["lower_method_name"] = LowerMethodName(method); + p->Print(*vars, + "$lower_method_name$ = createMethodDescriptor(\n" + " \"$Package$$service_name$\", $method_field_name$);\n"); + } + p->Outdent(); + p->Print("}\n"); + + // The reconfiguring constructor + p->Print( + *vars, + "\nprivate $service_name$ServiceDescriptor(\n" + " $Map$<$String$, $MethodDescriptor$> methodMap) {\n"); + p->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["input_type"] = MessageFullJavaName(method->input_type()); + (*vars)["output_type"] = MessageFullJavaName(method->output_type()); + (*vars)["lower_method_name"] = LowerMethodName(method); + (*vars)["method_field_name"] = MethodPropertiesFieldName(method); + p->Print( + *vars, + "$lower_method_name$ = ($MethodDescriptor$<$input_type$,\n" + " $output_type$>) methodMap.get(\n" + " CONFIG.$lower_method_name$.getName());\n"); + } + p->Outdent(); + p->Print("}\n\n"); + + p->Print( + *vars, + "@$Override$\nprotected $service_name$ServiceDescriptor build(\n" + " $Map$<$String$, $MethodDescriptor$> methodMap) {\n"); + p->Indent(); + p->Print( + *vars, + "return new $service_name$ServiceDescriptor(methodMap);\n"); + p->Outdent(); + p->Print("}\n\n"); + + p->Print( + *vars, + "@$Override$\n" + "public $ImmutableList$<$MethodDescriptor$> methods() {\n"); + p->Indent(); + p->Print( + *vars, + "return $ImmutableList$.<$MethodDescriptor$>of(\n"); + p->Indent(); + p->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + p->Print(MixedLower(service->method(i)->name()).c_str()); + if (i < service->method_count() - 1) { + p->Print(",\n"); + } else { + p->Print(");\n"); + } + } + p->Outdent(); + p->Outdent(); + p->Outdent(); + p->Print("}\n"); + + p->Outdent(); + p->Print("}\n\n"); +} + +enum StubType { + ASYNC_INTERFACE = 0, + BLOCKING_CLIENT_INTERFACE = 1, + FUTURE_CLIENT_INTERFACE = 2, + BLOCKING_SERVER_INTERFACE = 3, + ASYNC_CLIENT_IMPL = 4, + BLOCKING_CLIENT_IMPL = 5, + FUTURE_CLIENT_IMPL = 6 +}; + +enum CallType { + ASYNC_CALL = 0, + BLOCKING_CALL = 1, + FUTURE_CALL = 2 +}; + +// Prints a client interface or implementation class, or a server interface. +static void PrintStub(const google::protobuf::ServiceDescriptor* service, + map* vars, + Printer* p, StubType type) { + (*vars)["service_name"] = service->name(); + string interface_name = service->name(); + string impl_name = service->name(); + switch (type) { + case ASYNC_INTERFACE: + case ASYNC_CLIENT_IMPL: + impl_name += "Stub"; + break; + case BLOCKING_CLIENT_INTERFACE: + case BLOCKING_CLIENT_IMPL: + interface_name += "BlockingClient"; + impl_name += "BlockingStub"; + break; + case FUTURE_CLIENT_INTERFACE: + case FUTURE_CLIENT_IMPL: + interface_name += "FutureClient"; + impl_name += "FutureStub"; + break; + case BLOCKING_SERVER_INTERFACE: + interface_name += "BlockingServer"; + break; + default: + LOG(FATAL) << "Unsupported type: " << type; + } + bool impl; + CallType call_type; + switch (type) { + case ASYNC_INTERFACE: + call_type = ASYNC_CALL; + impl = false; + break; + case BLOCKING_CLIENT_INTERFACE: + case BLOCKING_SERVER_INTERFACE: + call_type = BLOCKING_CALL; + impl = false; + break; + case FUTURE_CLIENT_INTERFACE: + call_type = FUTURE_CALL; + impl = false; + break; + case ASYNC_CLIENT_IMPL: + call_type = ASYNC_CALL; + impl = true; + break; + case BLOCKING_CLIENT_IMPL: + call_type = BLOCKING_CALL; + impl = true; + break; + case FUTURE_CLIENT_IMPL: + call_type = FUTURE_CALL; + impl = true; + break; + default: + LOG(FATAL) << "Unsupported type: " << type; + } + (*vars)["interface_name"] = interface_name; + (*vars)["impl_name"] = impl_name; + + // Class head + if (!impl) { + p->Print( + *vars, + "public static interface $interface_name$ {\n"); + } else { + p->Print( + *vars, + "public static class $impl_name$ extends\n" + " $AbstractStub$<$impl_name$, $service_name$ServiceDescriptor>\n" + " implements $interface_name$ {\n"); + } + p->Indent(); + + // Constructor and build() method + if (impl) { + p->Print( + *vars, + "private $impl_name$($Channel$ channel,\n" + " $service_name$ServiceDescriptor config) {\n"); + p->Indent(); + p->Print("super(channel, config);\n"); + p->Outdent(); + p->Print("}\n\n"); + p->Print( + *vars, + "@$Override$\n" + "protected $impl_name$ build($Channel$ channel,\n" + " $service_name$ServiceDescriptor config) {\n"); + p->Indent(); + p->Print( + *vars, + "return new $impl_name$(channel, config);\n"); + p->Outdent(); + p->Print("}\n"); + } + + // RPC methods + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["input_type"] = MessageFullJavaName(method->input_type()); + (*vars)["output_type"] = MessageFullJavaName(method->output_type()); + (*vars)["lower_method_name"] = LowerMethodName(method); + bool client_streaming = method->client_streaming(); + bool server_streaming = method->server_streaming(); + + if (call_type == BLOCKING_CALL && client_streaming) { + // Blocking client interface with client streaming is not available + continue; + } + + if (call_type == FUTURE_CALL && (client_streaming || server_streaming)) { + // Future interface doesn't support streaming. + continue; + } + + // Method signature + p->Print("\n"); + if (impl) { + p->Print( + *vars, + "@$Override$\n"); + } + p->Print("public "); + switch (call_type) { + case BLOCKING_CALL: + // TODO(zhangkun): decide the blocking server interface + CHECK(type != BLOCKING_SERVER_INTERFACE) + << "Blocking server interface is not available"; + CHECK(!client_streaming) + << "Blocking client interface with client streaming is unavailable"; + if (server_streaming) { + // Server streaming + p->Print( + *vars, + "$Iterator$<$output_type$> $lower_method_name$(\n" + " $input_type$ request)"); + } else { + // Simple RPC + p->Print( + *vars, + "$output_type$ $lower_method_name$($input_type$ request)"); + } + break; + case ASYNC_CALL: + if (client_streaming) { + // Duplex streaming or client streaming + p->Print( + *vars, + "$StreamObserver$<$input_type$> $lower_method_name$(\n" + " $StreamObserver$<$output_type$> responseObserver)"); + } else { + // Server streaming or simple RPC + p->Print( + *vars, + "void $lower_method_name$($input_type$ request,\n" + " $StreamObserver$<$output_type$> responseObserver)"); + } + break; + case FUTURE_CALL: + CHECK(!client_streaming && !server_streaming) + << "Future interface doesn't support streaming. " + << "client_streaming=" << client_streaming << ", " + << "server_streaming=" << server_streaming; + p->Print( + *vars, + "$ListenableFuture$<$output_type$> $lower_method_name$(\n" + " $input_type$ request)"); + break; + } + if (impl) { + // Method body for client impls + p->Print(" {\n"); + p->Indent(); + switch (call_type) { + case BLOCKING_CALL: + CHECK(!client_streaming) + << "Blocking client streaming interface is not available"; + if (server_streaming) { + (*vars)["calls_method"] = "blockingServerStreamingCall"; + (*vars)["params"] = "request"; + } else { + (*vars)["calls_method"] = "blockingUnaryCall"; + (*vars)["params"] = "request"; + } + p->Print( + *vars, + "return $calls_method$(\n" + " channel.newCall(config.$lower_method_name$), $params$);\n"); + break; + case ASYNC_CALL: + if (server_streaming) { + if (client_streaming) { + (*vars)["calls_method"] = "duplexStreamingCall"; + (*vars)["params"] = "responseObserver"; + } else { + (*vars)["calls_method"] = "asyncServerStreamingCall"; + (*vars)["params"] = "request, responseObserver"; + } + } else { + if (client_streaming) { + (*vars)["calls_method"] = "asyncClientStreamingCall"; + (*vars)["params"] = "responseObserver"; + } else { + (*vars)["calls_method"] = "asyncUnaryCall"; + (*vars)["params"] = "request, responseObserver"; + } + } + (*vars)["last_line_prefix"] = client_streaming ? "return " : ""; + p->Print( + *vars, + "$last_line_prefix$$calls_method$(\n" + " channel.newCall(config.$lower_method_name$), $params$);\n"); + break; + case FUTURE_CALL: + CHECK(!client_streaming && !server_streaming) + << "Future interface doesn't support streaming. " + << "client_streaming=" << client_streaming << ", " + << "server_streaming=" << server_streaming; + (*vars)["calls_method"] = "unaryFutureCall"; + p->Print( + *vars, + "return $calls_method$(\n" + " channel.newCall(config.$lower_method_name$), request);\n"); + break; + } + p->Outdent(); + p->Print("}\n"); + } else { + p->Print(";\n"); + } + } + p->Outdent(); + p->Print("}\n\n"); +} + +static void PrintBindServiceMethod(const ServiceDescriptor* service, + map* vars, + Printer* p) { + (*vars)["service_name"] = service->name(); + p->Print( + *vars, + "public static $ServerServiceDefinition$ bindService(\n" + " final $service_name$ serviceImpl) {\n"); + p->Indent(); + p->Print(*vars, + "return " + "$ServerServiceDefinition$.builder(\"$Package$$service_name$\")\n"); + p->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["lower_method_name"] = LowerMethodName(method); + (*vars)["method_field_name"] = MethodPropertiesFieldName(method); + (*vars)["input_type"] = MessageFullJavaName(method->input_type()); + (*vars)["output_type"] = MessageFullJavaName(method->output_type()); + bool client_streaming = method->client_streaming(); + if (client_streaming) { + (*vars)["calls_method"] = "asyncStreamingRequestCall"; + (*vars)["invocation_class"] = + "com.google.net.stubby.stub.ServerCalls.StreamingRequestMethod"; + } else { + (*vars)["calls_method"] = "asyncUnaryRequestCall"; + (*vars)["invocation_class"] = + "com.google.net.stubby.stub.ServerCalls.UnaryRequestMethod"; + } + p->Print(*vars, ".addMethod(createMethodDefinition(\n"); + p->Indent(); + p->Indent(); + p->Print( + *vars, + "$method_field_name$,\n" + "$calls_method$(\n"); + p->Indent(); + p->Print( + *vars, + "new $invocation_class$<\n" + " $input_type$,\n" + " $output_type$>() {\n"); + p->Indent(); + p->Print( + *vars, + "@$Override$\n"); + if (client_streaming) { + p->Print( + *vars, + "public $StreamObserver$<$input_type$> invoke(\n" + " $StreamObserver$<$output_type$> responseObserver) {\n" + " return serviceImpl.$lower_method_name$(responseObserver);\n" + "}\n"); + } else { + p->Print( + *vars, + "public void invoke(\n" + " $input_type$ request,\n" + " $StreamObserver$<$output_type$> responseObserver) {\n" + " serviceImpl.$lower_method_name$(request, responseObserver);\n" + "}\n"); + } + p->Outdent(); + p->Print("})))"); + if (i == service->method_count() - 1) { + p->Print(".build();"); + } + p->Print("\n"); + p->Outdent(); + p->Outdent(); + p->Outdent(); + } + p->Outdent(); + p->Outdent(); + p->Print("}\n"); +} + +static void PrintService(const ServiceDescriptor* service, + map* vars, + Printer* p) { + (*vars)["service_name"] = service->name(); + (*vars)["service_class_name"] = ServiceClassName(service); + p->Print( + *vars, + "@$Generated$(\"by gRPC proto compiler\")\n" + "public class $service_class_name$ {\n\n"); + p->Indent(); + + PrintMethodFields(service, vars, p); + + p->Print( + *vars, + "public static $service_name$Stub newStub($Channel$ channel) {\n"); + p->Indent(); + p->Print( + *vars, + "return new $service_name$Stub(channel, CONFIG);\n"); + p->Outdent(); + p->Print("}\n\n"); + p->Print( + *vars, + "public static $service_name$BlockingStub newBlockingStub(\n" + " $Channel$ channel) {\n"); + p->Indent(); + p->Print( + *vars, + "return new $service_name$BlockingStub(channel, CONFIG);\n"); + p->Outdent(); + p->Print("}\n\n"); + p->Print( + *vars, + "public static $service_name$FutureStub newFutureStub(\n" + " $Channel$ channel) {\n"); + p->Indent(); + p->Print( + *vars, + "return new $service_name$FutureStub(channel, CONFIG);\n"); + p->Outdent(); + p->Print("}\n\n"); + + p->Print( + *vars, + "public static final $service_name$ServiceDescriptor CONFIG =\n" + " new $service_name$ServiceDescriptor();\n\n"); + PrintServiceDescriptor(service, vars, p); + PrintStub(service, vars, p, ASYNC_INTERFACE); + PrintStub(service, vars, p, BLOCKING_CLIENT_INTERFACE); + PrintStub(service, vars, p, FUTURE_CLIENT_INTERFACE); + PrintStub(service, vars, p, ASYNC_CLIENT_IMPL); + PrintStub(service, vars, p, BLOCKING_CLIENT_IMPL); + PrintStub(service, vars, p, FUTURE_CLIENT_IMPL); + PrintBindServiceMethod(service, vars, p); + p->Outdent(); + p->Print("}\n"); +} + +void PrintImports(Printer* p) { + p->Print( + "import static " + "com.google.net.stubby.stub.Calls.createMethodDescriptor;\n" + "import static " + "com.google.net.stubby.stub.Calls.asyncUnaryCall;\n" + "import static " + "com.google.net.stubby.stub.Calls.asyncServerStreamingCall;\n" + "import static " + "com.google.net.stubby.stub.Calls.asyncClientStreamingCall;\n" + "import static " + "com.google.net.stubby.stub.Calls.duplexStreamingCall;\n" + "import static " + "com.google.net.stubby.stub.Calls.blockingUnaryCall;\n" + "import static " + "com.google.net.stubby.stub.Calls.blockingServerStreamingCall;\n" + "import static " + "com.google.net.stubby.stub.Calls.unaryFutureCall;\n" + "import static " + "com.google.net.stubby.stub.ServerCalls.createMethodDefinition;\n" + "import static " + "com.google.net.stubby.stub.ServerCalls.asyncUnaryRequestCall;\n" + "import static " + "com.google.net.stubby.stub.ServerCalls.asyncStreamingRequestCall;\n\n"); +} + +void GenerateService(const ServiceDescriptor* service, + google::protobuf::io::ZeroCopyOutputStream* out) { + // All non-generated classes must be referred by fully qualified names to + // avoid collision with generated classes. + map vars; + vars["String"] = "java.lang.String"; + vars["Override"] = "java.lang.Override"; + vars["Channel"] = "com.google.net.stubby.Channel"; + vars["MethodType"] = "com.google.net.stubby.MethodType"; + vars["ServerServiceDefinition"] = + "com.google.net.stubby.ServerServiceDefinition"; + vars["AbstractStub"] = "com.google.net.stubby.stub.AbstractStub"; + vars["Method"] = "com.google.net.stubby.stub.Method"; + vars["AbstractServiceDescriptor"] = + "com.google.net.stubby.stub.AbstractServiceDescriptor"; + vars["ImmutableList"] = "com.google.common.collect.ImmutableList"; + vars["MethodDescriptor"] = "com.google.net.stubby.MethodDescriptor"; + vars["ProtoUtils"] = "com.google.net.stubby.proto.ProtoUtils"; + vars["StreamObserver"] = "com.google.net.stubby.stub.StreamObserver"; + vars["Iterator"] = "java.util.Iterator"; + vars["Map"] = "java.util.Map"; + vars["TimeUnit"] = "java.util.concurrent.TimeUnit"; + vars["Generated"] = "javax.annotation.Generated"; + vars["Immutable"] = "javax.annotation.concurrent.Immutable"; + vars["ListenableFuture"] = + "com.google.common.util.concurrent.ListenableFuture"; + + Printer printer(out, '$'); + string package_name = ServiceJavaPackage(service->file()); + printer.Print( + "package $package_name$;\n\n", + "package_name", package_name); + PrintImports(&printer); + + // Package string is used to fully qualify method names. + vars["Package"] = service->file()->package(); + if (!vars["Package"].empty()) { + vars["Package"].append("."); + } + PrintService(service, &vars, &printer); +} + +string ServiceJavaPackage(const FileDescriptor* file) { + string result = google::protobuf::compiler::java::ClassName(file); + size_t last_dot_pos = result.find_last_of('.'); + if (last_dot_pos != string::npos) { + result.resize(last_dot_pos); + } + return result; +} + +string ServiceClassName(const google::protobuf::ServiceDescriptor* service) { + return service->name() + "Grpc"; +} + +} // namespace java_grpc_generator diff --git a/src/compiler/java_generator.h b/src/compiler/java_generator.h new file mode 100644 index 00000000000..58da1254cb8 --- /dev/null +++ b/src/compiler/java_generator.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NET_GRPC_COMPILER_JAVA_GENERATOR_H_ +#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_ + +#include +#include + +namespace java_grpc_generator { + +// Returns the package name of the gRPC services defined in the given file. +string ServiceJavaPackage(const google::protobuf::FileDescriptor* file); + +// Returns the name of the outer class that wraps in all the generated code for +// the given service. +string ServiceClassName(const google::protobuf::ServiceDescriptor* service); + +// Writes the generated service interface into the given ZeroCopyOutputStream +void GenerateService(const google::protobuf::ServiceDescriptor* service, + google::protobuf::io::ZeroCopyOutputStream* out); + +} // namespace java_grpc_generator + +#endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_ diff --git a/src/compiler/java_plugin.cc b/src/compiler/java_plugin.cc new file mode 100644 index 00000000000..f6f327291b5 --- /dev/null +++ b/src/compiler/java_plugin.cc @@ -0,0 +1,84 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Generates Java gRPC service interface out of Protobuf IDL. +// +// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto +// and net/proto2/compiler/public/plugin.h for more information on plugins. + +#include + +#include "src/compiler/java_generator.h" +#include +#include +#include +#include + +static string JavaPackageToDir(const string& package_name) { + string package_dir = package_name; + for (size_t i = 0; i < package_dir.size(); ++i) { + if (package_dir[i] == '.') { + package_dir[i] = '/'; + } + } + if (!package_dir.empty()) package_dir += "/"; + return package_dir; +} + +class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator { + public: + JavaGrpcGenerator() {} + virtual ~JavaGrpcGenerator() {} + + virtual bool Generate(const google::protobuf::FileDescriptor* file, + const string& parameter, + google::protobuf::compiler::GeneratorContext* context, + string* error) const { + string package_name = java_grpc_generator::ServiceJavaPackage(file); + string package_filename = JavaPackageToDir(package_name); + for (int i = 0; i < file->service_count(); ++i) { + const google::protobuf::ServiceDescriptor* service = file->service(i); + string filename = package_filename + + java_grpc_generator::ServiceClassName(service) + ".java"; + std::unique_ptr output( + context->Open(filename)); + java_grpc_generator::GenerateService(service, output.get()); + } + return true; + } +}; + +int main(int argc, char* argv[]) { + JavaGrpcGenerator generator; + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +} From 440d3d819864bcfd1f917494cbedb62166cfda3e Mon Sep 17 00:00:00 2001 From: hongyu Date: Fri, 9 Jan 2015 12:39:36 -0800 Subject: [PATCH 16/29] Grpc census: v0 trace_printf() implementation in C. Change on 2015/01/09 by hongyu ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83626942 --- src/core/statistics/census_tracing.c | 30 +++++++++++++++++++++++----- test/core/statistics/trace_test.c | 26 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/core/statistics/census_tracing.c b/src/core/statistics/census_tracing.c index d37c427c5b2..45302cd6abe 100644 --- a/src/core/statistics/census_tracing.c +++ b/src/core/statistics/census_tracing.c @@ -47,8 +47,8 @@ /* Struct for a trace annotation. */ typedef struct annotation { - gpr_uint64 ts; /* timestamp of the annotation */ - char txt[CENSUS_MAX_ANNOTATION_LENGTH]; /* actual txt annotation */ + gpr_timespec ts; /* timestamp of the annotation */ + char txt[CENSUS_MAX_ANNOTATION_LENGTH + 1]; /* actual txt annotation */ struct annotation* next; } annotation; @@ -107,8 +107,8 @@ census_op_id census_tracing_start_op() { ret->rpc_stats.cnt = 1; ret->ts = gpr_now(); census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void*)ret); + gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id); gpr_mu_unlock(&g_mu); - gpr_log(GPR_DEBUG, "Start tracing for id %lu\n", g_id); return ret->id; } } @@ -127,7 +127,27 @@ int census_add_method_tag(census_op_id op_id, const char* method) { return ret; } -void census_tracing_print(census_op_id op_id, const char* annotation) {} +void census_tracing_print(census_op_id op_id, const char* anno_txt) { + trace_obj* trace = NULL; + gpr_mu_lock(&g_mu); + trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); + if (trace != NULL) { + annotation* anno = gpr_malloc(sizeof(annotation)); + anno->ts = gpr_now(); + { + char* d = anno->txt; + const char* s = anno_txt; + int n = 0; + for (; n < CENSUS_MAX_ANNOTATION_LENGTH && *s != '\0'; ++n) { + *d++ = *s++; + } + *d = '\0'; + } + anno->next = trace->annotations; + trace->annotations = anno; + } + gpr_mu_unlock(&g_mu); +} void census_tracing_end_op(census_op_id op_id) { trace_obj* trace = NULL; @@ -136,7 +156,7 @@ void census_tracing_end_op(census_op_id op_id) { if (trace != NULL) { trace->rpc_stats.elapsed_time_ms = gpr_timespec_to_micros(gpr_time_sub(gpr_now(), trace->ts)); - gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us\n", + gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us", op_id_2_uint64(&op_id), trace->method, trace->rpc_stats.elapsed_time_ms); census_ht_erase(g_trace_store, op_id_as_key(&op_id)); diff --git a/test/core/statistics/trace_test.c b/test/core/statistics/trace_test.c index b06fbd574b2..9a6c54b90fe 100644 --- a/test/core/statistics/trace_test.c +++ b/test/core/statistics/trace_test.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "test/core/util/test_config.h" /* Ensure all possible state transitions are called without causing problem */ @@ -130,10 +131,12 @@ static void test_concurrency() { for (i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(tid + i, mimic_trace_op_sequences, &arg, NULL); } + gpr_mu_lock(&arg.mu); while (arg.num_done < NUM_THREADS) { gpr_log(GPR_INFO, "num done %d", arg.num_done); gpr_cv_wait(&arg.done, &arg.mu, gpr_inf_future); } + gpr_mu_unlock(&arg.mu); census_tracing_shutdown(); #undef NUM_THREADS } @@ -147,6 +150,28 @@ static void test_add_method_tag_to_unknown_op_id() { census_tracing_shutdown(); } +static void test_trace_print() { + census_op_id id; + int i; + const char* annotation_txt[4] = {"abc", "", "$%^ *()_"}; + char long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 10]; + + memset(long_txt, 'a', GPR_ARRAY_SIZE(long_txt)); + long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 9] = '\0'; + annotation_txt[3] = long_txt; + + census_tracing_init(); + id = census_tracing_start_op(); + /* Adds large number of annotations to each trace */ + for (i = 0; i < 1000; i++) { + census_tracing_print(id, + annotation_txt[i % GPR_ARRAY_SIZE(annotation_txt)]); + } + census_tracing_end_op(id); + + census_tracing_shutdown(); +} + int main(int argc, char** argv) { grpc_test_init(argc, argv); test_init_shutdown(); @@ -154,5 +179,6 @@ int main(int argc, char** argv) { test_get_trace_method_name(); test_concurrency(); test_add_method_tag_to_unknown_op_id(); + test_trace_print(); return 0; } From 08c50d8bf5fb30291407e9860b732da6c654418e Mon Sep 17 00:00:00 2001 From: ctiller Date: Fri, 9 Jan 2015 12:47:03 -0800 Subject: [PATCH 17/29] Make generate_projects.sh able to run from a git repo. Change on 2015/01/09 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83627504 --- tools/buildgen/generate_projects.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/buildgen/generate_projects.sh b/tools/buildgen/generate_projects.sh index f4e367d620a..8358e3aea67 100755 --- a/tools/buildgen/generate_projects.sh +++ b/tools/buildgen/generate_projects.sh @@ -1,13 +1,13 @@ #!/bin/bash -set -ex +set -x if [ "x$TEST" == "x" ] ; then TEST=false fi -cd `dirname $0`/.. +cd `dirname $0`/../.. mako_renderer=tools/buildgen/mako_renderer.py gen_build_json=test/core/end2end/gen_build_json.py @@ -33,8 +33,6 @@ for dir in . ; do if [ $TEST == true ] ; then actual_out=$out out=`mktemp` - else - g4 open $out || true fi $mako_renderer $plugins $data -o $out $file if [ $TEST == true ] ; then From 5d61ac074c26a1631cfdbd34d590c730139a9de6 Mon Sep 17 00:00:00 2001 From: zhangkun Date: Fri, 9 Jan 2015 14:06:48 -0800 Subject: [PATCH 18/29] Undo the addition of Java codegen files to the open-sourced list by [] because it breaks MOE scrubber for GPRC. Change on 2015/01/09 by zhangkun ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83633678 --- src/compiler/java_generator.cc | 701 --------------------------------- src/compiler/java_generator.h | 55 --- src/compiler/java_plugin.cc | 84 ---- 3 files changed, 840 deletions(-) delete mode 100644 src/compiler/java_generator.cc delete mode 100644 src/compiler/java_generator.h delete mode 100644 src/compiler/java_plugin.cc diff --git a/src/compiler/java_generator.cc b/src/compiler/java_generator.cc deleted file mode 100644 index 6915bbfcb20..00000000000 --- a/src/compiler/java_generator.cc +++ /dev/null @@ -1,701 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/compiler/java_generator.h" - -#include -#include "net/proto2/compiler/java/public/names.h" -#include -#include -#include "net/proto_compiler/proto.h" -#include "net/proto_compiler/proto-inl.h" - -namespace java_grpc_generator { - -using google::protobuf::FileDescriptor; -using google::protobuf::ServiceDescriptor; -using google::protobuf::MethodDescriptor; -using google::protobuf::Descriptor; -using google::protobuf::io::Printer; - -// Adjust a method name prefix identifier to follow the JavaBean spec: -// - decapitalize the first letter -// - remove embedded underscores & capitalize the following letter -static string MixedLower(const string& word) { - string w; - w += tolower(word[0]); - bool after_underscore = false; - for (int i = 1; i < word.length(); ++i) { - if (word[i] == '_') { - after_underscore = true; - } else { - w += after_underscore ? toupper(word[i]) : word[i]; - after_underscore = false; - } - } - return w; -} - -// Converts to the identifier to the ALL_UPPER_CASE format. -// - An underscore is inserted where a lower case letter is followed by an -// upper case letter. -// - All letters are converted to upper case -static string ToAllUpperCase(const string& word) { - string w; - for (int i = 0; i < word.length(); ++i) { - w += toupper(word[i]); - if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) { - w += '_'; - } - } - return w; -} - -static inline string LowerMethodName(const MethodDescriptor* method) { - return MixedLower(method->name()); -} - -static inline string MethodPropertiesFieldName(const MethodDescriptor* method) { - return "METHOD_" + ToAllUpperCase(method->name()); -} - -static inline string MessageFullJavaName(const Descriptor* desc) { - return google::protobuf::compiler::java::ClassName(desc); -} - -static void PrintMethodFields( - const ServiceDescriptor* service, map* vars, Printer* p) { - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - (*vars)["method_name"] = method->name(); - (*vars)["input_type"] = MessageFullJavaName(method->input_type()); - (*vars)["output_type"] = MessageFullJavaName(method->output_type()); - (*vars)["method_field_name"] = MethodPropertiesFieldName(method); - bool client_streaming = method->client_streaming(); - bool server_streaming = method->server_streaming(); - if (client_streaming) { - if (server_streaming) { - (*vars)["method_type"] = "DUPLEX_STREAMING"; - } else { - (*vars)["method_type"] = "CLIENT_STREAMING"; - } - } else { - if (server_streaming) { - (*vars)["method_type"] = "SERVER_STREAMING"; - } else { - (*vars)["method_type"] = "UNARY"; - } - } - p->Print( - *vars, - "private static final $Method$<$input_type$,\n" - " $output_type$> $method_field_name$ =\n" - " $Method$.create(\n" - " $MethodType$.$method_type$, \"$method_name$\",\n" - " $ProtoUtils$.marshaller($input_type$.PARSER),\n" - " $ProtoUtils$.marshaller($output_type$.PARSER));\n"); - } - p->Print("\n"); -} - -static void PrintServiceDescriptor( - const ServiceDescriptor* service, map* vars, Printer* p) { - (*vars)["service_name"] = service->name(); - p->Print( - *vars, - "@$Immutable$\n"); - p->Print( - *vars, - "public static class $service_name$ServiceDescriptor extends\n" - " $AbstractServiceDescriptor$<$service_name$ServiceDescriptor> {\n"); - p->Indent(); - - // Service descriptor fields - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - (*vars)["input_type"] = MessageFullJavaName(method->input_type()); - (*vars)["output_type"] = MessageFullJavaName(method->output_type()); - (*vars)["lower_method_name"] = LowerMethodName(method); - p->Print( - *vars, - "public final $MethodDescriptor$<$input_type$,\n" - " $output_type$> $lower_method_name$;\n"); - } - - // The default constructor - p->Print( - *vars, - "\nprivate $service_name$ServiceDescriptor() {\n"); - p->Indent(); - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - (*vars)["method_field_name"] = MethodPropertiesFieldName(method); - (*vars)["lower_method_name"] = LowerMethodName(method); - p->Print(*vars, - "$lower_method_name$ = createMethodDescriptor(\n" - " \"$Package$$service_name$\", $method_field_name$);\n"); - } - p->Outdent(); - p->Print("}\n"); - - // The reconfiguring constructor - p->Print( - *vars, - "\nprivate $service_name$ServiceDescriptor(\n" - " $Map$<$String$, $MethodDescriptor$> methodMap) {\n"); - p->Indent(); - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - (*vars)["input_type"] = MessageFullJavaName(method->input_type()); - (*vars)["output_type"] = MessageFullJavaName(method->output_type()); - (*vars)["lower_method_name"] = LowerMethodName(method); - (*vars)["method_field_name"] = MethodPropertiesFieldName(method); - p->Print( - *vars, - "$lower_method_name$ = ($MethodDescriptor$<$input_type$,\n" - " $output_type$>) methodMap.get(\n" - " CONFIG.$lower_method_name$.getName());\n"); - } - p->Outdent(); - p->Print("}\n\n"); - - p->Print( - *vars, - "@$Override$\nprotected $service_name$ServiceDescriptor build(\n" - " $Map$<$String$, $MethodDescriptor$> methodMap) {\n"); - p->Indent(); - p->Print( - *vars, - "return new $service_name$ServiceDescriptor(methodMap);\n"); - p->Outdent(); - p->Print("}\n\n"); - - p->Print( - *vars, - "@$Override$\n" - "public $ImmutableList$<$MethodDescriptor$> methods() {\n"); - p->Indent(); - p->Print( - *vars, - "return $ImmutableList$.<$MethodDescriptor$>of(\n"); - p->Indent(); - p->Indent(); - for (int i = 0; i < service->method_count(); ++i) { - p->Print(MixedLower(service->method(i)->name()).c_str()); - if (i < service->method_count() - 1) { - p->Print(",\n"); - } else { - p->Print(");\n"); - } - } - p->Outdent(); - p->Outdent(); - p->Outdent(); - p->Print("}\n"); - - p->Outdent(); - p->Print("}\n\n"); -} - -enum StubType { - ASYNC_INTERFACE = 0, - BLOCKING_CLIENT_INTERFACE = 1, - FUTURE_CLIENT_INTERFACE = 2, - BLOCKING_SERVER_INTERFACE = 3, - ASYNC_CLIENT_IMPL = 4, - BLOCKING_CLIENT_IMPL = 5, - FUTURE_CLIENT_IMPL = 6 -}; - -enum CallType { - ASYNC_CALL = 0, - BLOCKING_CALL = 1, - FUTURE_CALL = 2 -}; - -// Prints a client interface or implementation class, or a server interface. -static void PrintStub(const google::protobuf::ServiceDescriptor* service, - map* vars, - Printer* p, StubType type) { - (*vars)["service_name"] = service->name(); - string interface_name = service->name(); - string impl_name = service->name(); - switch (type) { - case ASYNC_INTERFACE: - case ASYNC_CLIENT_IMPL: - impl_name += "Stub"; - break; - case BLOCKING_CLIENT_INTERFACE: - case BLOCKING_CLIENT_IMPL: - interface_name += "BlockingClient"; - impl_name += "BlockingStub"; - break; - case FUTURE_CLIENT_INTERFACE: - case FUTURE_CLIENT_IMPL: - interface_name += "FutureClient"; - impl_name += "FutureStub"; - break; - case BLOCKING_SERVER_INTERFACE: - interface_name += "BlockingServer"; - break; - default: - LOG(FATAL) << "Unsupported type: " << type; - } - bool impl; - CallType call_type; - switch (type) { - case ASYNC_INTERFACE: - call_type = ASYNC_CALL; - impl = false; - break; - case BLOCKING_CLIENT_INTERFACE: - case BLOCKING_SERVER_INTERFACE: - call_type = BLOCKING_CALL; - impl = false; - break; - case FUTURE_CLIENT_INTERFACE: - call_type = FUTURE_CALL; - impl = false; - break; - case ASYNC_CLIENT_IMPL: - call_type = ASYNC_CALL; - impl = true; - break; - case BLOCKING_CLIENT_IMPL: - call_type = BLOCKING_CALL; - impl = true; - break; - case FUTURE_CLIENT_IMPL: - call_type = FUTURE_CALL; - impl = true; - break; - default: - LOG(FATAL) << "Unsupported type: " << type; - } - (*vars)["interface_name"] = interface_name; - (*vars)["impl_name"] = impl_name; - - // Class head - if (!impl) { - p->Print( - *vars, - "public static interface $interface_name$ {\n"); - } else { - p->Print( - *vars, - "public static class $impl_name$ extends\n" - " $AbstractStub$<$impl_name$, $service_name$ServiceDescriptor>\n" - " implements $interface_name$ {\n"); - } - p->Indent(); - - // Constructor and build() method - if (impl) { - p->Print( - *vars, - "private $impl_name$($Channel$ channel,\n" - " $service_name$ServiceDescriptor config) {\n"); - p->Indent(); - p->Print("super(channel, config);\n"); - p->Outdent(); - p->Print("}\n\n"); - p->Print( - *vars, - "@$Override$\n" - "protected $impl_name$ build($Channel$ channel,\n" - " $service_name$ServiceDescriptor config) {\n"); - p->Indent(); - p->Print( - *vars, - "return new $impl_name$(channel, config);\n"); - p->Outdent(); - p->Print("}\n"); - } - - // RPC methods - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - (*vars)["input_type"] = MessageFullJavaName(method->input_type()); - (*vars)["output_type"] = MessageFullJavaName(method->output_type()); - (*vars)["lower_method_name"] = LowerMethodName(method); - bool client_streaming = method->client_streaming(); - bool server_streaming = method->server_streaming(); - - if (call_type == BLOCKING_CALL && client_streaming) { - // Blocking client interface with client streaming is not available - continue; - } - - if (call_type == FUTURE_CALL && (client_streaming || server_streaming)) { - // Future interface doesn't support streaming. - continue; - } - - // Method signature - p->Print("\n"); - if (impl) { - p->Print( - *vars, - "@$Override$\n"); - } - p->Print("public "); - switch (call_type) { - case BLOCKING_CALL: - // TODO(zhangkun): decide the blocking server interface - CHECK(type != BLOCKING_SERVER_INTERFACE) - << "Blocking server interface is not available"; - CHECK(!client_streaming) - << "Blocking client interface with client streaming is unavailable"; - if (server_streaming) { - // Server streaming - p->Print( - *vars, - "$Iterator$<$output_type$> $lower_method_name$(\n" - " $input_type$ request)"); - } else { - // Simple RPC - p->Print( - *vars, - "$output_type$ $lower_method_name$($input_type$ request)"); - } - break; - case ASYNC_CALL: - if (client_streaming) { - // Duplex streaming or client streaming - p->Print( - *vars, - "$StreamObserver$<$input_type$> $lower_method_name$(\n" - " $StreamObserver$<$output_type$> responseObserver)"); - } else { - // Server streaming or simple RPC - p->Print( - *vars, - "void $lower_method_name$($input_type$ request,\n" - " $StreamObserver$<$output_type$> responseObserver)"); - } - break; - case FUTURE_CALL: - CHECK(!client_streaming && !server_streaming) - << "Future interface doesn't support streaming. " - << "client_streaming=" << client_streaming << ", " - << "server_streaming=" << server_streaming; - p->Print( - *vars, - "$ListenableFuture$<$output_type$> $lower_method_name$(\n" - " $input_type$ request)"); - break; - } - if (impl) { - // Method body for client impls - p->Print(" {\n"); - p->Indent(); - switch (call_type) { - case BLOCKING_CALL: - CHECK(!client_streaming) - << "Blocking client streaming interface is not available"; - if (server_streaming) { - (*vars)["calls_method"] = "blockingServerStreamingCall"; - (*vars)["params"] = "request"; - } else { - (*vars)["calls_method"] = "blockingUnaryCall"; - (*vars)["params"] = "request"; - } - p->Print( - *vars, - "return $calls_method$(\n" - " channel.newCall(config.$lower_method_name$), $params$);\n"); - break; - case ASYNC_CALL: - if (server_streaming) { - if (client_streaming) { - (*vars)["calls_method"] = "duplexStreamingCall"; - (*vars)["params"] = "responseObserver"; - } else { - (*vars)["calls_method"] = "asyncServerStreamingCall"; - (*vars)["params"] = "request, responseObserver"; - } - } else { - if (client_streaming) { - (*vars)["calls_method"] = "asyncClientStreamingCall"; - (*vars)["params"] = "responseObserver"; - } else { - (*vars)["calls_method"] = "asyncUnaryCall"; - (*vars)["params"] = "request, responseObserver"; - } - } - (*vars)["last_line_prefix"] = client_streaming ? "return " : ""; - p->Print( - *vars, - "$last_line_prefix$$calls_method$(\n" - " channel.newCall(config.$lower_method_name$), $params$);\n"); - break; - case FUTURE_CALL: - CHECK(!client_streaming && !server_streaming) - << "Future interface doesn't support streaming. " - << "client_streaming=" << client_streaming << ", " - << "server_streaming=" << server_streaming; - (*vars)["calls_method"] = "unaryFutureCall"; - p->Print( - *vars, - "return $calls_method$(\n" - " channel.newCall(config.$lower_method_name$), request);\n"); - break; - } - p->Outdent(); - p->Print("}\n"); - } else { - p->Print(";\n"); - } - } - p->Outdent(); - p->Print("}\n\n"); -} - -static void PrintBindServiceMethod(const ServiceDescriptor* service, - map* vars, - Printer* p) { - (*vars)["service_name"] = service->name(); - p->Print( - *vars, - "public static $ServerServiceDefinition$ bindService(\n" - " final $service_name$ serviceImpl) {\n"); - p->Indent(); - p->Print(*vars, - "return " - "$ServerServiceDefinition$.builder(\"$Package$$service_name$\")\n"); - p->Indent(); - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - (*vars)["lower_method_name"] = LowerMethodName(method); - (*vars)["method_field_name"] = MethodPropertiesFieldName(method); - (*vars)["input_type"] = MessageFullJavaName(method->input_type()); - (*vars)["output_type"] = MessageFullJavaName(method->output_type()); - bool client_streaming = method->client_streaming(); - if (client_streaming) { - (*vars)["calls_method"] = "asyncStreamingRequestCall"; - (*vars)["invocation_class"] = - "com.google.net.stubby.stub.ServerCalls.StreamingRequestMethod"; - } else { - (*vars)["calls_method"] = "asyncUnaryRequestCall"; - (*vars)["invocation_class"] = - "com.google.net.stubby.stub.ServerCalls.UnaryRequestMethod"; - } - p->Print(*vars, ".addMethod(createMethodDefinition(\n"); - p->Indent(); - p->Indent(); - p->Print( - *vars, - "$method_field_name$,\n" - "$calls_method$(\n"); - p->Indent(); - p->Print( - *vars, - "new $invocation_class$<\n" - " $input_type$,\n" - " $output_type$>() {\n"); - p->Indent(); - p->Print( - *vars, - "@$Override$\n"); - if (client_streaming) { - p->Print( - *vars, - "public $StreamObserver$<$input_type$> invoke(\n" - " $StreamObserver$<$output_type$> responseObserver) {\n" - " return serviceImpl.$lower_method_name$(responseObserver);\n" - "}\n"); - } else { - p->Print( - *vars, - "public void invoke(\n" - " $input_type$ request,\n" - " $StreamObserver$<$output_type$> responseObserver) {\n" - " serviceImpl.$lower_method_name$(request, responseObserver);\n" - "}\n"); - } - p->Outdent(); - p->Print("})))"); - if (i == service->method_count() - 1) { - p->Print(".build();"); - } - p->Print("\n"); - p->Outdent(); - p->Outdent(); - p->Outdent(); - } - p->Outdent(); - p->Outdent(); - p->Print("}\n"); -} - -static void PrintService(const ServiceDescriptor* service, - map* vars, - Printer* p) { - (*vars)["service_name"] = service->name(); - (*vars)["service_class_name"] = ServiceClassName(service); - p->Print( - *vars, - "@$Generated$(\"by gRPC proto compiler\")\n" - "public class $service_class_name$ {\n\n"); - p->Indent(); - - PrintMethodFields(service, vars, p); - - p->Print( - *vars, - "public static $service_name$Stub newStub($Channel$ channel) {\n"); - p->Indent(); - p->Print( - *vars, - "return new $service_name$Stub(channel, CONFIG);\n"); - p->Outdent(); - p->Print("}\n\n"); - p->Print( - *vars, - "public static $service_name$BlockingStub newBlockingStub(\n" - " $Channel$ channel) {\n"); - p->Indent(); - p->Print( - *vars, - "return new $service_name$BlockingStub(channel, CONFIG);\n"); - p->Outdent(); - p->Print("}\n\n"); - p->Print( - *vars, - "public static $service_name$FutureStub newFutureStub(\n" - " $Channel$ channel) {\n"); - p->Indent(); - p->Print( - *vars, - "return new $service_name$FutureStub(channel, CONFIG);\n"); - p->Outdent(); - p->Print("}\n\n"); - - p->Print( - *vars, - "public static final $service_name$ServiceDescriptor CONFIG =\n" - " new $service_name$ServiceDescriptor();\n\n"); - PrintServiceDescriptor(service, vars, p); - PrintStub(service, vars, p, ASYNC_INTERFACE); - PrintStub(service, vars, p, BLOCKING_CLIENT_INTERFACE); - PrintStub(service, vars, p, FUTURE_CLIENT_INTERFACE); - PrintStub(service, vars, p, ASYNC_CLIENT_IMPL); - PrintStub(service, vars, p, BLOCKING_CLIENT_IMPL); - PrintStub(service, vars, p, FUTURE_CLIENT_IMPL); - PrintBindServiceMethod(service, vars, p); - p->Outdent(); - p->Print("}\n"); -} - -void PrintImports(Printer* p) { - p->Print( - "import static " - "com.google.net.stubby.stub.Calls.createMethodDescriptor;\n" - "import static " - "com.google.net.stubby.stub.Calls.asyncUnaryCall;\n" - "import static " - "com.google.net.stubby.stub.Calls.asyncServerStreamingCall;\n" - "import static " - "com.google.net.stubby.stub.Calls.asyncClientStreamingCall;\n" - "import static " - "com.google.net.stubby.stub.Calls.duplexStreamingCall;\n" - "import static " - "com.google.net.stubby.stub.Calls.blockingUnaryCall;\n" - "import static " - "com.google.net.stubby.stub.Calls.blockingServerStreamingCall;\n" - "import static " - "com.google.net.stubby.stub.Calls.unaryFutureCall;\n" - "import static " - "com.google.net.stubby.stub.ServerCalls.createMethodDefinition;\n" - "import static " - "com.google.net.stubby.stub.ServerCalls.asyncUnaryRequestCall;\n" - "import static " - "com.google.net.stubby.stub.ServerCalls.asyncStreamingRequestCall;\n\n"); -} - -void GenerateService(const ServiceDescriptor* service, - google::protobuf::io::ZeroCopyOutputStream* out) { - // All non-generated classes must be referred by fully qualified names to - // avoid collision with generated classes. - map vars; - vars["String"] = "java.lang.String"; - vars["Override"] = "java.lang.Override"; - vars["Channel"] = "com.google.net.stubby.Channel"; - vars["MethodType"] = "com.google.net.stubby.MethodType"; - vars["ServerServiceDefinition"] = - "com.google.net.stubby.ServerServiceDefinition"; - vars["AbstractStub"] = "com.google.net.stubby.stub.AbstractStub"; - vars["Method"] = "com.google.net.stubby.stub.Method"; - vars["AbstractServiceDescriptor"] = - "com.google.net.stubby.stub.AbstractServiceDescriptor"; - vars["ImmutableList"] = "com.google.common.collect.ImmutableList"; - vars["MethodDescriptor"] = "com.google.net.stubby.MethodDescriptor"; - vars["ProtoUtils"] = "com.google.net.stubby.proto.ProtoUtils"; - vars["StreamObserver"] = "com.google.net.stubby.stub.StreamObserver"; - vars["Iterator"] = "java.util.Iterator"; - vars["Map"] = "java.util.Map"; - vars["TimeUnit"] = "java.util.concurrent.TimeUnit"; - vars["Generated"] = "javax.annotation.Generated"; - vars["Immutable"] = "javax.annotation.concurrent.Immutable"; - vars["ListenableFuture"] = - "com.google.common.util.concurrent.ListenableFuture"; - - Printer printer(out, '$'); - string package_name = ServiceJavaPackage(service->file()); - printer.Print( - "package $package_name$;\n\n", - "package_name", package_name); - PrintImports(&printer); - - // Package string is used to fully qualify method names. - vars["Package"] = service->file()->package(); - if (!vars["Package"].empty()) { - vars["Package"].append("."); - } - PrintService(service, &vars, &printer); -} - -string ServiceJavaPackage(const FileDescriptor* file) { - string result = google::protobuf::compiler::java::ClassName(file); - size_t last_dot_pos = result.find_last_of('.'); - if (last_dot_pos != string::npos) { - result.resize(last_dot_pos); - } - return result; -} - -string ServiceClassName(const google::protobuf::ServiceDescriptor* service) { - return service->name() + "Grpc"; -} - -} // namespace java_grpc_generator diff --git a/src/compiler/java_generator.h b/src/compiler/java_generator.h deleted file mode 100644 index 58da1254cb8..00000000000 --- a/src/compiler/java_generator.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NET_GRPC_COMPILER_JAVA_GENERATOR_H_ -#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_ - -#include -#include - -namespace java_grpc_generator { - -// Returns the package name of the gRPC services defined in the given file. -string ServiceJavaPackage(const google::protobuf::FileDescriptor* file); - -// Returns the name of the outer class that wraps in all the generated code for -// the given service. -string ServiceClassName(const google::protobuf::ServiceDescriptor* service); - -// Writes the generated service interface into the given ZeroCopyOutputStream -void GenerateService(const google::protobuf::ServiceDescriptor* service, - google::protobuf::io::ZeroCopyOutputStream* out); - -} // namespace java_grpc_generator - -#endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_ diff --git a/src/compiler/java_plugin.cc b/src/compiler/java_plugin.cc deleted file mode 100644 index f6f327291b5..00000000000 --- a/src/compiler/java_plugin.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -// Generates Java gRPC service interface out of Protobuf IDL. -// -// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto -// and net/proto2/compiler/public/plugin.h for more information on plugins. - -#include - -#include "src/compiler/java_generator.h" -#include -#include -#include -#include - -static string JavaPackageToDir(const string& package_name) { - string package_dir = package_name; - for (size_t i = 0; i < package_dir.size(); ++i) { - if (package_dir[i] == '.') { - package_dir[i] = '/'; - } - } - if (!package_dir.empty()) package_dir += "/"; - return package_dir; -} - -class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator { - public: - JavaGrpcGenerator() {} - virtual ~JavaGrpcGenerator() {} - - virtual bool Generate(const google::protobuf::FileDescriptor* file, - const string& parameter, - google::protobuf::compiler::GeneratorContext* context, - string* error) const { - string package_name = java_grpc_generator::ServiceJavaPackage(file); - string package_filename = JavaPackageToDir(package_name); - for (int i = 0; i < file->service_count(); ++i) { - const google::protobuf::ServiceDescriptor* service = file->service(i); - string filename = package_filename - + java_grpc_generator::ServiceClassName(service) + ".java"; - std::unique_ptr output( - context->Open(filename)); - java_grpc_generator::GenerateService(service, output.get()); - } - return true; - } -}; - -int main(int argc, char* argv[]) { - JavaGrpcGenerator generator; - return google::protobuf::compiler::PluginMain(argc, argv, &generator); -} From 4105e2b86c91ecc3687def3abcbb602bee894b0a Mon Sep 17 00:00:00 2001 From: yangg Date: Fri, 9 Jan 2015 14:19:44 -0800 Subject: [PATCH 19/29] Add ServiceAccount Credentials wrapping and handle credentials creation failure. Change on 2015/01/09 by yangg ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83634736 --- Makefile | 45 +++++++++++++++-- build.json | 12 +++++ include/grpc++/create_channel.h | 1 + include/grpc++/credentials.h | 30 ++++++++++++ src/core/security/security_context.c | 12 +++-- src/core/surface/lame_client.c | 29 +++++++++-- src/cpp/client/channel.cc | 10 +++- src/cpp/client/credentials.cc | 37 ++++++++++++-- src/cpp/stream/stream_context.cc | 4 ++ test/cpp/client/credentials_test.cc | 73 ++++++++++++++++++++++++++++ test/cpp/end2end/end2end_test.cc | 33 +++++++++++++ 11 files changed, 271 insertions(+), 15 deletions(-) create mode 100644 test/cpp/client/credentials_test.cc diff --git a/Makefile b/Makefile index 8be41960452..a1c76e155df 100644 --- a/Makefile +++ b/Makefile @@ -328,6 +328,7 @@ interop_server: bins/$(CONFIG)/interop_server interop_client: bins/$(CONFIG)/interop_client end2end_test: bins/$(CONFIG)/end2end_test channel_arguments_test: bins/$(CONFIG)/channel_arguments_test +credentials_test: bins/$(CONFIG)/credentials_test alarm_test: bins/$(CONFIG)/alarm_test alarm_list_test: bins/$(CONFIG)/alarm_list_test alarm_heap_test: bins/$(CONFIG)/alarm_heap_test @@ -493,7 +494,7 @@ buildtests: buildtests_c buildtests_cxx buildtests_c: bins_dep_c privatelibs_c bins/$(CONFIG)/grpc_byte_buffer_reader_test bins/$(CONFIG)/gpr_cancellable_test bins/$(CONFIG)/gpr_log_test bins/$(CONFIG)/gpr_useful_test bins/$(CONFIG)/gpr_cmdline_test bins/$(CONFIG)/gpr_histogram_test bins/$(CONFIG)/gpr_host_port_test bins/$(CONFIG)/gpr_slice_buffer_test bins/$(CONFIG)/gpr_slice_test bins/$(CONFIG)/gpr_string_test bins/$(CONFIG)/gpr_sync_test bins/$(CONFIG)/gpr_thd_test bins/$(CONFIG)/gpr_time_test bins/$(CONFIG)/murmur_hash_test bins/$(CONFIG)/grpc_stream_op_test bins/$(CONFIG)/alpn_test bins/$(CONFIG)/time_averaged_stats_test bins/$(CONFIG)/chttp2_stream_encoder_test bins/$(CONFIG)/hpack_table_test bins/$(CONFIG)/chttp2_stream_map_test bins/$(CONFIG)/hpack_parser_test bins/$(CONFIG)/transport_metadata_test bins/$(CONFIG)/chttp2_status_conversion_test bins/$(CONFIG)/chttp2_transport_end2end_test bins/$(CONFIG)/tcp_posix_test bins/$(CONFIG)/dualstack_socket_test bins/$(CONFIG)/no_server_test bins/$(CONFIG)/resolve_address_test bins/$(CONFIG)/sockaddr_utils_test bins/$(CONFIG)/tcp_server_posix_test bins/$(CONFIG)/tcp_client_posix_test bins/$(CONFIG)/grpc_channel_stack_test bins/$(CONFIG)/metadata_buffer_test bins/$(CONFIG)/grpc_completion_queue_test bins/$(CONFIG)/census_window_stats_test bins/$(CONFIG)/census_statistics_quick_test bins/$(CONFIG)/census_statistics_small_log_test bins/$(CONFIG)/census_statistics_performance_test bins/$(CONFIG)/census_statistics_multiple_writers_test bins/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test bins/$(CONFIG)/census_stub_test bins/$(CONFIG)/census_hash_table_test bins/$(CONFIG)/fling_server bins/$(CONFIG)/fling_client bins/$(CONFIG)/fling_test bins/$(CONFIG)/echo_server bins/$(CONFIG)/echo_client bins/$(CONFIG)/echo_test bins/$(CONFIG)/message_compress_test bins/$(CONFIG)/bin_encoder_test bins/$(CONFIG)/secure_endpoint_test bins/$(CONFIG)/httpcli_format_request_test bins/$(CONFIG)/httpcli_parser_test bins/$(CONFIG)/httpcli_test bins/$(CONFIG)/grpc_credentials_test bins/$(CONFIG)/grpc_base64_test bins/$(CONFIG)/grpc_json_token_test bins/$(CONFIG)/timeout_encoding_test bins/$(CONFIG)/fd_posix_test bins/$(CONFIG)/fling_stream_test bins/$(CONFIG)/lame_client_test bins/$(CONFIG)/alarm_test bins/$(CONFIG)/alarm_list_test bins/$(CONFIG)/alarm_heap_test bins/$(CONFIG)/time_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test bins/$(CONFIG)/chttp2_fake_security_disappearing_server_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fake_security_invoke_large_request_test bins/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fake_security_no_op_test bins/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test bins/$(CONFIG)/chttp2_fake_security_simple_request_test bins/$(CONFIG)/chttp2_fake_security_thread_stress_test bins/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fullstack_no_op_test bins/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_no_op_test bins/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test -buildtests_cxx: bins_dep_cxx privatelibs_cxx bins/thread_pool_test bins/status_test bins/sync_client_async_server_test bins/qps_client bins/qps_server bins/interop_server bins/interop_client bins/end2end_test bins/channel_arguments_test +buildtests_cxx: bins_dep_cxx privatelibs_cxx bins/thread_pool_test bins/status_test bins/sync_client_async_server_test bins/qps_client bins/qps_server bins/interop_server bins/interop_client bins/end2end_test bins/channel_arguments_test bins/credentials_test test: test_c test_cxx @@ -889,6 +890,8 @@ test_cxx: buildtests_cxx $(Q) ./bins/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 ) $(E) "[RUN] Testing channel_arguments_test" $(Q) ./bins/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 ) + $(E) "[RUN] Testing credentials_test" + $(Q) ./bins/$(CONFIG)/credentials_test || ( echo test credentials_test failed ; exit 1 ) tools: privatelibs bins/$(CONFIG)/gen_hpack_tables bins/$(CONFIG)/grpc_fetch_oauth2 @@ -1022,7 +1025,7 @@ bins_dep_c: deps_gen_hpack_tables deps_grpc_byte_buffer_reader_test deps_gpr_can dep_cxx: deps_libgrpc++ deps_libgrpc++_test_util -bins_dep_cxx: deps_cpp_plugin deps_ruby_plugin deps_thread_pool_test deps_status_test deps_sync_client_async_server_test deps_qps_client deps_qps_server deps_interop_server deps_interop_client deps_end2end_test deps_channel_arguments_test +bins_dep_cxx: deps_cpp_plugin deps_ruby_plugin deps_thread_pool_test deps_status_test deps_sync_client_async_server_test deps_qps_client deps_qps_server deps_interop_server deps_interop_client deps_end2end_test deps_channel_arguments_test deps_credentials_test install: install_c install_cxx @@ -1112,7 +1115,7 @@ ifneq ($(SYSTEM),Darwin) endif endif -clean: clean_libgpr clean_libgrpc clean_libgrpc_unsecure clean_libgrpc_test_util clean_libgrpc++ clean_libgrpc++_test_util clean_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_census_simple_request clean_libend2end_test_disappearing_server clean_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_invoke_large_request clean_libend2end_test_max_concurrent_streams clean_libend2end_test_no_op clean_libend2end_test_ping_pong_streaming clean_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_simple_delayed_request clean_libend2end_test_simple_request clean_libend2end_test_thread_stress clean_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_certs clean_gen_hpack_tables clean_cpp_plugin clean_ruby_plugin clean_grpc_byte_buffer_reader_test clean_gpr_cancellable_test clean_gpr_log_test clean_gpr_useful_test clean_gpr_cmdline_test clean_gpr_histogram_test clean_gpr_host_port_test clean_gpr_slice_buffer_test clean_gpr_slice_test clean_gpr_string_test clean_gpr_sync_test clean_gpr_thd_test clean_gpr_time_test clean_murmur_hash_test clean_grpc_stream_op_test clean_alpn_test clean_time_averaged_stats_test clean_chttp2_stream_encoder_test clean_hpack_table_test clean_chttp2_stream_map_test clean_hpack_parser_test clean_transport_metadata_test clean_chttp2_status_conversion_test clean_chttp2_transport_end2end_test clean_tcp_posix_test clean_dualstack_socket_test clean_no_server_test clean_resolve_address_test clean_sockaddr_utils_test clean_tcp_server_posix_test clean_tcp_client_posix_test clean_grpc_channel_stack_test clean_metadata_buffer_test clean_grpc_completion_queue_test clean_grpc_completion_queue_benchmark clean_census_trace_store_test clean_census_stats_store_test clean_census_window_stats_test clean_census_statistics_quick_test clean_census_statistics_small_log_test clean_census_statistics_performance_test clean_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_circular_buffer_test clean_census_stub_test clean_census_hash_table_test clean_fling_server clean_fling_client clean_fling_test clean_echo_server clean_echo_client clean_echo_test clean_low_level_ping_pong_benchmark clean_message_compress_test clean_bin_encoder_test clean_secure_endpoint_test clean_httpcli_format_request_test clean_httpcli_parser_test clean_httpcli_test clean_grpc_credentials_test clean_grpc_fetch_oauth2 clean_grpc_base64_test clean_grpc_json_token_test clean_timeout_encoding_test clean_fd_posix_test clean_fling_stream_test clean_lame_client_test clean_thread_pool_test clean_status_test clean_sync_client_async_server_test clean_qps_client clean_qps_server clean_interop_server clean_interop_client clean_end2end_test clean_channel_arguments_test clean_alarm_test clean_alarm_list_test clean_alarm_heap_test clean_time_test clean_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_no_op_test clean_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_no_op_test clean_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +clean: clean_libgpr clean_libgrpc clean_libgrpc_unsecure clean_libgrpc_test_util clean_libgrpc++ clean_libgrpc++_test_util clean_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_census_simple_request clean_libend2end_test_disappearing_server clean_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_invoke_large_request clean_libend2end_test_max_concurrent_streams clean_libend2end_test_no_op clean_libend2end_test_ping_pong_streaming clean_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_simple_delayed_request clean_libend2end_test_simple_request clean_libend2end_test_thread_stress clean_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_certs clean_gen_hpack_tables clean_cpp_plugin clean_ruby_plugin clean_grpc_byte_buffer_reader_test clean_gpr_cancellable_test clean_gpr_log_test clean_gpr_useful_test clean_gpr_cmdline_test clean_gpr_histogram_test clean_gpr_host_port_test clean_gpr_slice_buffer_test clean_gpr_slice_test clean_gpr_string_test clean_gpr_sync_test clean_gpr_thd_test clean_gpr_time_test clean_murmur_hash_test clean_grpc_stream_op_test clean_alpn_test clean_time_averaged_stats_test clean_chttp2_stream_encoder_test clean_hpack_table_test clean_chttp2_stream_map_test clean_hpack_parser_test clean_transport_metadata_test clean_chttp2_status_conversion_test clean_chttp2_transport_end2end_test clean_tcp_posix_test clean_dualstack_socket_test clean_no_server_test clean_resolve_address_test clean_sockaddr_utils_test clean_tcp_server_posix_test clean_tcp_client_posix_test clean_grpc_channel_stack_test clean_metadata_buffer_test clean_grpc_completion_queue_test clean_grpc_completion_queue_benchmark clean_census_trace_store_test clean_census_stats_store_test clean_census_window_stats_test clean_census_statistics_quick_test clean_census_statistics_small_log_test clean_census_statistics_performance_test clean_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_circular_buffer_test clean_census_stub_test clean_census_hash_table_test clean_fling_server clean_fling_client clean_fling_test clean_echo_server clean_echo_client clean_echo_test clean_low_level_ping_pong_benchmark clean_message_compress_test clean_bin_encoder_test clean_secure_endpoint_test clean_httpcli_format_request_test clean_httpcli_parser_test clean_httpcli_test clean_grpc_credentials_test clean_grpc_fetch_oauth2 clean_grpc_base64_test clean_grpc_json_token_test clean_timeout_encoding_test clean_fd_posix_test clean_fling_stream_test clean_lame_client_test clean_thread_pool_test clean_status_test clean_sync_client_async_server_test clean_qps_client clean_qps_server clean_interop_server clean_interop_client clean_end2end_test clean_channel_arguments_test clean_credentials_test clean_alarm_test clean_alarm_list_test clean_alarm_heap_test clean_time_test clean_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_no_op_test clean_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_no_op_test clean_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(Q) $(RM) -r deps objs libs bins gens @@ -5275,6 +5278,40 @@ clean_channel_arguments_test: $(Q) $(RM) bins/$(CONFIG)/channel_arguments_test +CREDENTIALS_TEST_SRC = \ + test/cpp/client/credentials_test.cc \ + +CREDENTIALS_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CREDENTIALS_TEST_SRC)))) +CREDENTIALS_TEST_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(CREDENTIALS_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +bins/$(CONFIG)/credentials_test: openssl_dep_error + +else + +bins/$(CONFIG)/credentials_test: $(CREDENTIALS_TEST_OBJS) libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(CREDENTIALS_TEST_OBJS) $(GTEST_LIB) libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a $(LDLIBSXX) $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/credentials_test + +endif + +deps_credentials_test: $(CREDENTIALS_TEST_DEPS) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CREDENTIALS_TEST_DEPS) +endif +endif + +clean_credentials_test: + $(E) "[CLEAN] Cleaning credentials_test files" + $(Q) $(RM) $(CREDENTIALS_TEST_OBJS) + $(Q) $(RM) $(CREDENTIALS_TEST_DEPS) + $(Q) $(RM) bins/$(CONFIG)/credentials_test + + ALARM_TEST_SRC = \ test/core/iomgr/alarm_test.c \ @@ -9573,4 +9610,4 @@ clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_ -.PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx clean dep_c dep_cxx bins_dep_c bins_dep_cxx deps_libgpr clean_libgpr deps_libgrpc clean_libgrpc deps_libgrpc_unsecure clean_libgrpc_unsecure deps_libgrpc_test_util clean_libgrpc_test_util deps_libgrpc++ clean_libgrpc++ deps_libgrpc++_test_util clean_libgrpc++_test_util deps_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_census_simple_request clean_libend2end_test_census_simple_request deps_libend2end_test_disappearing_server clean_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request clean_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams clean_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op clean_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming clean_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request clean_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request clean_libend2end_test_simple_request deps_libend2end_test_thread_stress clean_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs clean_libend2end_certs deps_gen_hpack_tables clean_gen_hpack_tables deps_cpp_plugin clean_cpp_plugin deps_ruby_plugin clean_ruby_plugin deps_grpc_byte_buffer_reader_test clean_grpc_byte_buffer_reader_test deps_gpr_cancellable_test clean_gpr_cancellable_test deps_gpr_log_test clean_gpr_log_test deps_gpr_useful_test clean_gpr_useful_test deps_gpr_cmdline_test clean_gpr_cmdline_test deps_gpr_histogram_test clean_gpr_histogram_test deps_gpr_host_port_test clean_gpr_host_port_test deps_gpr_slice_buffer_test clean_gpr_slice_buffer_test deps_gpr_slice_test clean_gpr_slice_test deps_gpr_string_test clean_gpr_string_test deps_gpr_sync_test clean_gpr_sync_test deps_gpr_thd_test clean_gpr_thd_test deps_gpr_time_test clean_gpr_time_test deps_murmur_hash_test clean_murmur_hash_test deps_grpc_stream_op_test clean_grpc_stream_op_test deps_alpn_test clean_alpn_test deps_time_averaged_stats_test clean_time_averaged_stats_test deps_chttp2_stream_encoder_test clean_chttp2_stream_encoder_test deps_hpack_table_test clean_hpack_table_test deps_chttp2_stream_map_test clean_chttp2_stream_map_test deps_hpack_parser_test clean_hpack_parser_test deps_transport_metadata_test clean_transport_metadata_test deps_chttp2_status_conversion_test clean_chttp2_status_conversion_test deps_chttp2_transport_end2end_test clean_chttp2_transport_end2end_test deps_tcp_posix_test clean_tcp_posix_test deps_dualstack_socket_test clean_dualstack_socket_test deps_no_server_test clean_no_server_test deps_resolve_address_test clean_resolve_address_test deps_sockaddr_utils_test clean_sockaddr_utils_test deps_tcp_server_posix_test clean_tcp_server_posix_test deps_tcp_client_posix_test clean_tcp_client_posix_test deps_grpc_channel_stack_test clean_grpc_channel_stack_test deps_metadata_buffer_test clean_metadata_buffer_test deps_grpc_completion_queue_test clean_grpc_completion_queue_test deps_grpc_completion_queue_benchmark clean_grpc_completion_queue_benchmark deps_census_trace_store_test clean_census_trace_store_test deps_census_stats_store_test clean_census_stats_store_test deps_census_window_stats_test clean_census_window_stats_test deps_census_statistics_quick_test clean_census_statistics_quick_test deps_census_statistics_small_log_test clean_census_statistics_small_log_test deps_census_statistics_performance_test clean_census_statistics_performance_test deps_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test clean_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test clean_census_stub_test deps_census_hash_table_test clean_census_hash_table_test deps_fling_server clean_fling_server deps_fling_client clean_fling_client deps_fling_test clean_fling_test deps_echo_server clean_echo_server deps_echo_client clean_echo_client deps_echo_test clean_echo_test deps_low_level_ping_pong_benchmark clean_low_level_ping_pong_benchmark deps_message_compress_test clean_message_compress_test deps_bin_encoder_test clean_bin_encoder_test deps_secure_endpoint_test clean_secure_endpoint_test deps_httpcli_format_request_test clean_httpcli_format_request_test deps_httpcli_parser_test clean_httpcli_parser_test deps_httpcli_test clean_httpcli_test deps_grpc_credentials_test clean_grpc_credentials_test deps_grpc_fetch_oauth2 clean_grpc_fetch_oauth2 deps_grpc_base64_test clean_grpc_base64_test deps_grpc_json_token_test clean_grpc_json_token_test deps_timeout_encoding_test clean_timeout_encoding_test deps_fd_posix_test clean_fd_posix_test deps_fling_stream_test clean_fling_stream_test deps_lame_client_test clean_lame_client_test deps_thread_pool_test clean_thread_pool_test deps_status_test clean_status_test deps_sync_client_async_server_test clean_sync_client_async_server_test deps_qps_client clean_qps_client deps_qps_server clean_qps_server deps_interop_server clean_interop_server deps_interop_client clean_interop_client deps_end2end_test clean_end2end_test deps_channel_arguments_test clean_channel_arguments_test deps_alarm_test clean_alarm_test deps_alarm_list_test clean_alarm_list_test deps_alarm_heap_test clean_alarm_heap_test deps_time_test clean_time_test deps_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_census_simple_request_test deps_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test clean_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_census_simple_request_test deps_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test clean_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_census_simple_request_test deps_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +.PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx clean dep_c dep_cxx bins_dep_c bins_dep_cxx deps_libgpr clean_libgpr deps_libgrpc clean_libgrpc deps_libgrpc_unsecure clean_libgrpc_unsecure deps_libgrpc_test_util clean_libgrpc_test_util deps_libgrpc++ clean_libgrpc++ deps_libgrpc++_test_util clean_libgrpc++_test_util deps_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_census_simple_request clean_libend2end_test_census_simple_request deps_libend2end_test_disappearing_server clean_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request clean_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams clean_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op clean_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming clean_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request clean_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request clean_libend2end_test_simple_request deps_libend2end_test_thread_stress clean_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs clean_libend2end_certs deps_gen_hpack_tables clean_gen_hpack_tables deps_cpp_plugin clean_cpp_plugin deps_ruby_plugin clean_ruby_plugin deps_grpc_byte_buffer_reader_test clean_grpc_byte_buffer_reader_test deps_gpr_cancellable_test clean_gpr_cancellable_test deps_gpr_log_test clean_gpr_log_test deps_gpr_useful_test clean_gpr_useful_test deps_gpr_cmdline_test clean_gpr_cmdline_test deps_gpr_histogram_test clean_gpr_histogram_test deps_gpr_host_port_test clean_gpr_host_port_test deps_gpr_slice_buffer_test clean_gpr_slice_buffer_test deps_gpr_slice_test clean_gpr_slice_test deps_gpr_string_test clean_gpr_string_test deps_gpr_sync_test clean_gpr_sync_test deps_gpr_thd_test clean_gpr_thd_test deps_gpr_time_test clean_gpr_time_test deps_murmur_hash_test clean_murmur_hash_test deps_grpc_stream_op_test clean_grpc_stream_op_test deps_alpn_test clean_alpn_test deps_time_averaged_stats_test clean_time_averaged_stats_test deps_chttp2_stream_encoder_test clean_chttp2_stream_encoder_test deps_hpack_table_test clean_hpack_table_test deps_chttp2_stream_map_test clean_chttp2_stream_map_test deps_hpack_parser_test clean_hpack_parser_test deps_transport_metadata_test clean_transport_metadata_test deps_chttp2_status_conversion_test clean_chttp2_status_conversion_test deps_chttp2_transport_end2end_test clean_chttp2_transport_end2end_test deps_tcp_posix_test clean_tcp_posix_test deps_dualstack_socket_test clean_dualstack_socket_test deps_no_server_test clean_no_server_test deps_resolve_address_test clean_resolve_address_test deps_sockaddr_utils_test clean_sockaddr_utils_test deps_tcp_server_posix_test clean_tcp_server_posix_test deps_tcp_client_posix_test clean_tcp_client_posix_test deps_grpc_channel_stack_test clean_grpc_channel_stack_test deps_metadata_buffer_test clean_metadata_buffer_test deps_grpc_completion_queue_test clean_grpc_completion_queue_test deps_grpc_completion_queue_benchmark clean_grpc_completion_queue_benchmark deps_census_trace_store_test clean_census_trace_store_test deps_census_stats_store_test clean_census_stats_store_test deps_census_window_stats_test clean_census_window_stats_test deps_census_statistics_quick_test clean_census_statistics_quick_test deps_census_statistics_small_log_test clean_census_statistics_small_log_test deps_census_statistics_performance_test clean_census_statistics_performance_test deps_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test clean_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test clean_census_stub_test deps_census_hash_table_test clean_census_hash_table_test deps_fling_server clean_fling_server deps_fling_client clean_fling_client deps_fling_test clean_fling_test deps_echo_server clean_echo_server deps_echo_client clean_echo_client deps_echo_test clean_echo_test deps_low_level_ping_pong_benchmark clean_low_level_ping_pong_benchmark deps_message_compress_test clean_message_compress_test deps_bin_encoder_test clean_bin_encoder_test deps_secure_endpoint_test clean_secure_endpoint_test deps_httpcli_format_request_test clean_httpcli_format_request_test deps_httpcli_parser_test clean_httpcli_parser_test deps_httpcli_test clean_httpcli_test deps_grpc_credentials_test clean_grpc_credentials_test deps_grpc_fetch_oauth2 clean_grpc_fetch_oauth2 deps_grpc_base64_test clean_grpc_base64_test deps_grpc_json_token_test clean_grpc_json_token_test deps_timeout_encoding_test clean_timeout_encoding_test deps_fd_posix_test clean_fd_posix_test deps_fling_stream_test clean_fling_stream_test deps_lame_client_test clean_lame_client_test deps_thread_pool_test clean_thread_pool_test deps_status_test clean_status_test deps_sync_client_async_server_test clean_sync_client_async_server_test deps_qps_client clean_qps_client deps_qps_server clean_qps_server deps_interop_server clean_interop_server deps_interop_client clean_interop_client deps_end2end_test clean_end2end_test deps_channel_arguments_test clean_channel_arguments_test deps_credentials_test clean_credentials_test deps_alarm_test clean_alarm_test deps_alarm_list_test clean_alarm_list_test deps_alarm_heap_test clean_alarm_heap_test deps_time_test clean_time_test deps_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_census_simple_request_test deps_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test clean_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_census_simple_request_test deps_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test clean_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_census_simple_request_test deps_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test diff --git a/build.json b/build.json index 25415720a55..df59c0460ad 100644 --- a/build.json +++ b/build.json @@ -1369,6 +1369,18 @@ "grpc" ] }, + { + "name": "credentials_test", + "build": "test", + "c++": true, + "src": [ + "test/cpp/client/credentials_test.cc" + ], + "deps": [ + "grpc++", + "grpc" + ] + }, { "name": "alarm_test", "build": "test", diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h index 3253c9f1803..a8ce8b8ec84 100644 --- a/include/grpc++/create_channel.h +++ b/include/grpc++/create_channel.h @@ -46,6 +46,7 @@ class ChannelInterface; std::shared_ptr CreateChannel(const grpc::string& target, const ChannelArguments& args); +// If creds does not hold an object or is invalid, a lame channel is returned. std::shared_ptr CreateChannel( const grpc::string& target, const std::unique_ptr& creds, const ChannelArguments& args); diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h index 3ad12edaaeb..a8debbf7cf2 100644 --- a/include/grpc++/credentials.h +++ b/include/grpc++/credentials.h @@ -34,6 +34,7 @@ #ifndef __GRPCPP_CREDENTIALS_H_ #define __GRPCPP_CREDENTIALS_H_ +#include #include #include @@ -49,6 +50,7 @@ namespace grpc { class Credentials final { public: ~Credentials(); + // TODO(abhikumar): Specify a plugin API here to be implemented by // credentials that do not have a corresponding implementation in C. @@ -63,6 +65,15 @@ class Credentials final { }; // Options used to build SslCredentials +// pem_roots_cert is the buffer containing the PEM encoding of the server root +// certificates. This parameter cannot be empty. +// pem_private_key is the buffer containing the PEM encoding of the client's +// private key. This parameter can be empty if the client does not have a +// private key. +// pem_cert_chain is the buffer containing the PEM encoding of the client's +// certificate chain. This parameter can be empty if the client does not have +// a certificate chain. +// TODO(jboeuf) Change it to point to a file. struct SslCredentialsOptions { grpc::string pem_root_certs; grpc::string pem_private_key; @@ -70,6 +81,10 @@ struct SslCredentialsOptions { }; // Factory for building different types of Credentials +// The methods may return empty unique_ptr when credentials cannot be created. +// If a Credentials pointer is returned, it can still be invalid when used to +// create a channel. A lame channel will be created then and all rpcs will +// fail on it. class CredentialsFactory { public: // Builds credentials with reasonable defaults. @@ -82,6 +97,21 @@ class CredentialsFactory { // Builds credentials for use when running in GCE static std::unique_ptr ComputeEngineCredentials(); + // Builds service account credentials. + // json_key is the JSON key string containing the client's private key. + // scope is a space-delimited list of the requested permissions. + // token_lifetime is the lifetime of each token acquired through this service + // account credentials. It should be positive and should not exceed + // grpc_max_auth_token_lifetime or will be cropped to this value. + static std::unique_ptr ServiceAccountCredentials( + const grpc::string& json_key, const grpc::string& scope, + std::chrono::seconds token_lifetime); + + // Builds IAM credentials. + static std::unique_ptr IAMCredentials( + const grpc::string& authorization_token, + const grpc::string& authority_selector); + // Combines two credentials objects into a composite credentials static std::unique_ptr ComposeCredentials( diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index 13b9a847eeb..917a22f4538 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -451,7 +451,7 @@ static grpc_channel *grpc_ssl_channel_create(grpc_credentials *creds, grpc_security_status status = GRPC_SECURITY_OK; size_t i = 0; const char *secure_peer_name = target; - for (i = 0; i < args->num_args; i++) { + for (i = 0; args && i < args->num_args; i++) { grpc_arg *arg = &args->args[i]; if (!strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) && arg->type == GRPC_ARG_STRING) { @@ -492,12 +492,17 @@ static grpc_channel *grpc_channel_create_from_composite_creds( return grpc_ssl_channel_create( composite_creds, grpc_ssl_credentials_get_config(creds), target, args); } - return NULL; /* TODO(ctiller): return lame channel. */ + gpr_log(GPR_ERROR, "Credentials is insufficient to create a secure channel."); + return grpc_lame_client_channel_create(); } grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, const char *target, const grpc_channel_args *args) { + if (creds == NULL) { + gpr_log(GPR_ERROR, "No credentials to create a secure channel."); + return grpc_lame_client_channel_create(); + } if (grpc_credentials_has_request_metadata_only(creds)) { gpr_log(GPR_ERROR, "Credentials is insufficient to create a secure channel."); @@ -518,7 +523,8 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, return grpc_channel_create_from_composite_creds(creds, target, args); } else { gpr_log(GPR_ERROR, - "Unknown credentials type %s for creating a secure channel."); + "Unknown credentials type %s for creating a secure channel.", + creds->type); return grpc_lame_client_channel_create(); } } diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c index 6a832436cae..5fa3e42362c 100644 --- a/src/core/surface/lame_client.c +++ b/src/core/surface/lame_client.c @@ -33,6 +33,8 @@ #include "src/core/surface/lame_client.h" +#include + #include "src/core/channel/channel_stack.h" #include "src/core/surface/channel.h" #include "src/core/surface/call.h" @@ -42,16 +44,28 @@ typedef struct { void *unused; } call_data; -typedef struct { void *unused; } channel_data; +typedef struct { grpc_mdelem *message; } channel_data; + +static void do_nothing(void *data, grpc_op_error error) {} static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_op *op) { + channel_data *channeld = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { - case GRPC_SEND_START: + case GRPC_SEND_START: { + grpc_call_op set_status_op; + grpc_mdelem_ref(channeld->message); + memset(&set_status_op, 0, sizeof(grpc_call_op)); + set_status_op.dir = GRPC_CALL_UP; + set_status_op.type = GRPC_RECV_METADATA; + set_status_op.done_cb = do_nothing; + set_status_op.data.metadata = channeld->message; + grpc_call_recv_metadata(elem, &set_status_op); grpc_call_recv_finish(elem, 1); break; + } case GRPC_SEND_METADATA: grpc_mdelem_unref(op->data.metadata); break; @@ -81,11 +95,20 @@ static void destroy_call_elem(grpc_call_element *elem) {} static void init_channel_elem(grpc_channel_element *elem, const grpc_channel_args *args, grpc_mdctx *mdctx, int is_first, int is_last) { + channel_data *channeld = elem->channel_data; + GPR_ASSERT(is_first); GPR_ASSERT(is_last); + + channeld->message = grpc_mdelem_from_strings(mdctx, "grpc-message", + "Rpc sent on a lame channel."); } -static void destroy_channel_elem(grpc_channel_element *elem) {} +static void destroy_channel_elem(grpc_channel_element *elem) { + channel_data *channeld = elem->channel_data; + + grpc_mdelem_unref(channeld->message); +} static const grpc_channel_filter lame_filter = { call_op, channel_op, diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index 7d95518631f..6c8879d5775 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -69,8 +69,9 @@ Channel::Channel(const grpc::string& target, : args.GetSslTargetNameOverride()) { grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); + grpc_credentials* c_creds = creds ? creds->GetRawCreds() : nullptr; c_channel_ = grpc_secure_channel_create( - creds->GetRawCreds(), target.c_str(), + c_creds, target.c_str(), channel_args.num_args > 0 ? &channel_args : nullptr); } @@ -118,10 +119,15 @@ Status Channel::StartBlockingRpc(const RpcMethod& method, finished_tag, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); ev = grpc_completion_queue_pluck(cq, invoke_tag, gpr_inf_future); + bool success = ev->data.invoke_accepted == GRPC_OP_OK; grpc_event_finish(ev); + if (!success) { + GetFinalStatus(cq, finished_tag, &status); + return status; + } // write request grpc_byte_buffer* write_buffer = nullptr; - bool success = SerializeProto(request, &write_buffer); + success = SerializeProto(request, &write_buffer); if (!success) { grpc_call_cancel(call); status = diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc index 986008f7bb9..cac1d3d106c 100644 --- a/src/cpp/client/credentials.cc +++ b/src/cpp/client/credentials.cc @@ -35,6 +35,7 @@ #include #include +#include #include @@ -58,6 +59,9 @@ std::unique_ptr CredentialsFactory::SslCredentials( options.pem_root_certs.empty() ? nullptr : reinterpret_cast( options.pem_root_certs.c_str()); + if (pem_root_certs == nullptr) { + return std::unique_ptr(); + } const unsigned char* pem_private_key = options.pem_private_key.empty() ? nullptr : reinterpret_cast( @@ -71,14 +75,40 @@ std::unique_ptr CredentialsFactory::SslCredentials( pem_root_certs, options.pem_root_certs.size(), pem_private_key, options.pem_private_key.size(), pem_cert_chain, options.pem_cert_chain.size()); - std::unique_ptr cpp_creds(new Credentials(c_creds)); + std::unique_ptr cpp_creds( + c_creds == nullptr ? nullptr : new Credentials(c_creds)); return cpp_creds; } // Builds credentials for use when running in GCE std::unique_ptr CredentialsFactory::ComputeEngineCredentials() { grpc_credentials* c_creds = grpc_compute_engine_credentials_create(); - std::unique_ptr cpp_creds(new Credentials(c_creds)); + std::unique_ptr cpp_creds( + c_creds == nullptr ? nullptr : new Credentials(c_creds)); + return cpp_creds; +} + +// Builds service account credentials. +std::unique_ptr CredentialsFactory::ServiceAccountCredentials( + const grpc::string& json_key, const grpc::string& scope, + std::chrono::seconds token_lifetime) { + gpr_timespec lifetime = gpr_time_from_seconds( + token_lifetime.count() > 0 ? token_lifetime.count() : 0); + grpc_credentials* c_creds = grpc_service_account_credentials_create( + json_key.c_str(), scope.c_str(), lifetime); + std::unique_ptr cpp_creds( + c_creds == nullptr ? nullptr : new Credentials(c_creds)); + return cpp_creds; +} + +// Builds IAM credentials. +std::unique_ptr CredentialsFactory::IAMCredentials( + const grpc::string& authorization_token, + const grpc::string& authority_selector) { + grpc_credentials* c_creds = grpc_iam_credentials_create( + authorization_token.c_str(), authority_selector.c_str()); + std::unique_ptr cpp_creds( + c_creds == nullptr ? nullptr : new Credentials(c_creds)); return cpp_creds; } @@ -93,7 +123,8 @@ std::unique_ptr CredentialsFactory::ComposeCredentials( // refcounts incremented. grpc_credentials* c_creds = grpc_composite_credentials_create( creds1->GetRawCreds(), creds2->GetRawCreds()); - std::unique_ptr cpp_creds(new Credentials(c_creds)); + std::unique_ptr cpp_creds( + c_creds == nullptr ? nullptr : new Credentials(c_creds)); return cpp_creds; } diff --git a/src/cpp/stream/stream_context.cc b/src/cpp/stream/stream_context.cc index 22b7e7d494b..b55e647a632 100644 --- a/src/cpp/stream/stream_context.cc +++ b/src/cpp/stream/stream_context.cc @@ -85,6 +85,10 @@ void StreamContext::Start(bool buffered) { GPR_ASSERT(GRPC_CALL_OK == error); grpc_event* invoke_ev = grpc_completion_queue_pluck(cq(), invoke_tag(), gpr_inf_future); + if (invoke_ev->data.invoke_accepted != GRPC_OP_OK) { + peer_halfclosed_ = true; + self_halfclosed_ = true; + } grpc_event_finish(invoke_ev); } else { // TODO(yangg) metadata needs to be added before accept diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc new file mode 100644 index 00000000000..1bc95f9ff8a --- /dev/null +++ b/test/cpp/client/credentials_test.cc @@ -0,0 +1,73 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include + +#include +#include + +namespace grpc { +namespace testing { + +class CredentialsTest : public ::testing::Test { + protected: +}; + +TEST_F(CredentialsTest, InvalidSslCreds) { + std::unique_ptr bad1 = + CredentialsFactory::SslCredentials({"", "", ""}); + EXPECT_EQ(nullptr, bad1.get()); + std::unique_ptr bad2 = + CredentialsFactory::SslCredentials({"", "bla", "bla"}); + EXPECT_EQ(nullptr, bad2.get()); +} + +TEST_F(CredentialsTest, InvalidServiceAccountCreds) { + std::unique_ptr bad1 = + CredentialsFactory::ServiceAccountCredentials("", "", + std::chrono::seconds(1)); + EXPECT_EQ(nullptr, bad1.get()); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char **argv) { + + grpc_init(); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; +} diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index f63f6ad0763..1dcdd4202ca 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -401,6 +402,38 @@ TEST_F(End2endTest, DiffPackageServices) { EXPECT_TRUE(s.IsOk()); } +// rpc and stream should fail on bad credentials. +TEST_F(End2endTest, BadCredentials) { + std::unique_ptr bad_creds = + CredentialsFactory::ServiceAccountCredentials("", "", + std::chrono::seconds(1)); + EXPECT_EQ(nullptr, bad_creds.get()); + std::shared_ptr channel = + CreateChannel(server_address_.str(), bad_creds, ChannelArguments()); + std::unique_ptr stub( + grpc::cpp::test::util::TestService::NewStub(channel)); + EchoRequest request; + EchoResponse response; + ClientContext context; + grpc::string msg("hello"); + + Status s = stub->Echo(&context, request, &response); + EXPECT_EQ("", response.message()); + EXPECT_FALSE(s.IsOk()); + EXPECT_EQ(StatusCode::UNKNOWN, s.code()); + EXPECT_EQ("Rpc sent on a lame channel.", s.details()); + + ClientContext context2; + ClientReaderWriter* stream = + stub->BidiStream(&context2); + s = stream->Wait(); + EXPECT_FALSE(s.IsOk()); + EXPECT_EQ(StatusCode::UNKNOWN, s.code()); + EXPECT_EQ("Rpc sent on a lame channel.", s.details()); + + delete stream; +} + } // namespace testing } // namespace grpc From 033afb3879eba2d2e06091aa496b54066bddee07 Mon Sep 17 00:00:00 2001 From: ctiller Date: Fri, 9 Jan 2015 14:21:08 -0800 Subject: [PATCH 20/29] Fix for the Windows build Change on 2015/01/09 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83634893 --- include/grpc/support/port_platform.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h index 27a7b5529f7..9c999b9c811 100644 --- a/include/grpc/support/port_platform.h +++ b/include/grpc/support/port_platform.h @@ -126,8 +126,8 @@ #error Must define exactly one of GPR_ARCH_32, GPR_ARCH_64 #endif -#if defined(GPR_CPU_LINUX) + defined(GPR_CPU_POSIX) != 1 -#error Must define exactly one of GPR_CPU_LINUX, GPR_CPU_POSIX +#if defined(GPR_CPU_LINUX) + defined(GPR_CPU_POSIX) + defined(GPR_WIN32) != 1 +#error Must define exactly one of GPR_CPU_LINUX, GPR_CPU_POSIX, GPR_WIN32 #endif typedef int16_t gpr_int16; From 0cd69562fd8c005361e3f32ac0d3f9d43b713827 Mon Sep 17 00:00:00 2001 From: ctiller Date: Fri, 9 Jan 2015 14:22:10 -0800 Subject: [PATCH 21/29] Allow logging mechanism to be overridden by applications. This necessitated the removal of gpr_vlog to keep a clean interface. Change on 2015/01/09 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83634996 --- include/grpc/support/log.h | 18 ++++++++++-- src/core/channel/connected_channel.c | 43 +++++++++++++++------------- src/core/support/log.c | 23 +++++++++------ src/core/support/log_android.c | 24 ++++++++++------ src/core/support/log_linux.c | 28 +++++++++++------- src/core/support/log_posix.c | 41 +++++++++++++++++++------- src/core/support/log_win32.c | 40 ++++++++++++++++++++++---- test/core/support/log_test.c | 12 ++++++++ 8 files changed, 164 insertions(+), 65 deletions(-) diff --git a/include/grpc/support/log.h b/include/grpc/support/log.h index 5d0b7908673..f92114a8e3e 100644 --- a/include/grpc/support/log.h +++ b/include/grpc/support/log.h @@ -72,9 +72,21 @@ const char *gpr_log_severity_string(gpr_log_severity severity); void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format, ...); -/* Same as above, but using a va_list instead. */ -void gpr_vlog(const char *file, int line, gpr_log_severity severity, - const char *format, va_list args); +void gpr_log_message(const char *file, int line, gpr_log_severity severity, + const char *message); + +/* Log overrides: applications can use this API to intercept logging calls + and use their own implementations */ + +typedef struct { + const char *file; + int line; + gpr_log_severity severity; + const char *message; +} gpr_log_func_args; + +typedef void (*gpr_log_func)(gpr_log_func_args *args); +void gpr_set_log_function(gpr_log_func func); /* abort() the process if x is zero, having written a line to the log. diff --git a/src/core/channel/connected_channel.c b/src/core/channel/connected_channel.c index 5faa03c2f44..e01cb81a890 100644 --- a/src/core/channel/connected_channel.c +++ b/src/core/channel/connected_channel.c @@ -289,12 +289,8 @@ static void accept_stream(void *user_data, grpc_transport *transport, } static void recv_error(channel_data *chand, call_data *calld, int line, - const char *fmt, ...) { - va_list a; - - va_start(a, fmt); - gpr_vlog(__FILE__, line, GPR_LOG_SEVERITY_ERROR, fmt, a); - va_end(a); + const char *message) { + gpr_log_message(__FILE__, line, GPR_LOG_SEVERITY_ERROR, message); if (chand->transport) { grpc_transport_abort_stream(chand->transport, @@ -388,19 +384,23 @@ static void recv_batch(void *user_data, grpc_transport *transport, case GRPC_OP_BEGIN_MESSAGE: /* can't begin a message when we're still reading a message */ if (calld->reading_message) { - recv_error(chand, calld, __LINE__, - "Message terminated early; read %d bytes, expected %d", - calld->incoming_message.length, - calld->incoming_message_length); + char message[128]; + sprintf(message, + "Message terminated early; read %d bytes, expected %d", + (int)calld->incoming_message.length, + (int)calld->incoming_message_length); + recv_error(chand, calld, __LINE__, message); return; } /* stash away parameters, and prepare for incoming slices */ length = stream_op->data.begin_message.length; if (length > calld->max_message_length) { - recv_error( - chand, calld, __LINE__, + char message[128]; + sprintf( + message, "Maximum message length of %d exceeded by a message of length %d", calld->max_message_length, length); + recv_error(chand, calld, __LINE__, message); } else if (length > 0) { calld->reading_message = 1; calld->incoming_message_length = length; @@ -423,10 +423,12 @@ static void recv_batch(void *user_data, grpc_transport *transport, gpr_slice_buffer_add(&calld->incoming_message, stream_op->data.slice); if (calld->incoming_message.length > calld->incoming_message_length) { /* if we got too many bytes, complain */ - recv_error(chand, calld, __LINE__, - "Receiving message overflow; read %d bytes, expected %d", - calld->incoming_message.length, - calld->incoming_message_length); + char message[128]; + sprintf(message, + "Receiving message overflow; read %d bytes, expected %d", + (int)calld->incoming_message.length, + (int)calld->incoming_message_length); + recv_error(chand, calld, __LINE__, message); return; } else if (calld->incoming_message.length == calld->incoming_message_length) { @@ -439,10 +441,11 @@ static void recv_batch(void *user_data, grpc_transport *transport, final_state == GRPC_STREAM_CLOSED)) { calld->got_read_close = 1; if (calld->reading_message) { - recv_error(chand, calld, __LINE__, - "Last message truncated; read %d bytes, expected %d", - calld->incoming_message.length, - calld->incoming_message_length); + char message[128]; + sprintf(message, "Last message truncated; read %d bytes, expected %d", + (int)calld->incoming_message.length, + (int)calld->incoming_message_length); + recv_error(chand, calld, __LINE__, message); } call_op.type = GRPC_RECV_HALF_CLOSE; call_op.dir = GRPC_CALL_UP; diff --git a/src/core/support/log.c b/src/core/support/log.c index b9e2897efc3..7f102efea82 100644 --- a/src/core/support/log.c +++ b/src/core/support/log.c @@ -34,6 +34,10 @@ #include #include +#include + +extern void gpr_default_log(gpr_log_func_args *args); +static gpr_log_func g_log_func = gpr_default_log; const char *gpr_log_severity_string(gpr_log_severity severity) { switch (severity) { @@ -47,12 +51,15 @@ const char *gpr_log_severity_string(gpr_log_severity severity) { return "UNKNOWN"; } -void gpr_log(const char *file, int line, gpr_log_severity severity, - const char *format, ...) { - va_list args; - va_start(args, format); - - gpr_vlog(file, line, severity, format, args); - - va_end(args); +void gpr_log_message(const char *file, int line, gpr_log_severity severity, + const char *message) { + gpr_log_func_args lfargs; + memset(&lfargs, 0, sizeof(lfargs)); + lfargs.file = file; + lfargs.line = line; + lfargs.severity = severity; + lfargs.message = message; + g_log_func(&lfargs); } + +void gpr_set_log_function(gpr_log_func f) { g_log_func = f; } diff --git a/src/core/support/log_android.c b/src/core/support/log_android.c index 4c83e099146..11129e3e066 100644 --- a/src/core/support/log_android.c +++ b/src/core/support/log_android.c @@ -54,25 +54,31 @@ static android_LogPriority severity_to_log_priority(gpr_log_severity severity) { return ANDROID_LOG_DEFAULT; } -void gpr_vlog(const char *file, int line, gpr_log_severity severity, - const char *format, va_list args) { +void gpr_log(const char *file, int line, gpr_log_severity severity, + const char *format, ...) { + char *message = NULL; + va_list args; + va_start(args, format); + vasprintf(&message, format, args); + va_end(args); + gpr_log_message(file, line, severity, message); + free(message); +} + +void gpr_default_log(gpr_log_func_args *args) { char *final_slash; const char *display_file; - char *prefix = NULL; - char *suffix = NULL; char *output = NULL; - final_slash = strrchr(file, '/'); + final_slash = strrchr(args->file, '/'); if (final_slash == NULL) display_file = file; else display_file = final_slash + 1; - asprintf(&prefix, "%s:%d] ", display_file, line); - vasprintf(&suffix, format, args); - asprintf(&output, "%s%s", prefix, suffix); + asprintf(&prefix, "%s:%d] %s", display_file, args->line, args->message); - __android_log_write(severity_to_log_priority(severity), "GRPC", output); + __android_log_write(severity_to_log_priority(args->severity), "GRPC", output); /* allocated by asprintf => use free, not gpr_free */ free(prefix); diff --git a/src/core/support/log_linux.c b/src/core/support/log_linux.c index 322ff07dd90..f3b528bdc4d 100644 --- a/src/core/support/log_linux.c +++ b/src/core/support/log_linux.c @@ -49,17 +49,27 @@ static long gettid() { return syscall(__NR_gettid); } -void gpr_vlog(const char *file, int line, gpr_log_severity severity, - const char *format, va_list args) { +void gpr_log(const char *file, int line, gpr_log_severity severity, + const char *format, ...) { + char *message = NULL; + va_list args; + va_start(args, format); + vasprintf(&message, format, args); + va_end(args); + gpr_log_message(file, line, severity, message); + free(message); +} + +void gpr_default_log(gpr_log_func_args *args) { char *final_slash; const char *display_file; char time_buffer[64]; gpr_timespec now = gpr_now(); struct tm tm; - final_slash = strrchr(file, '/'); + final_slash = strrchr(args->file, '/'); if (final_slash == NULL) - display_file = file; + display_file = args->file; else display_file = final_slash + 1; @@ -70,12 +80,10 @@ void gpr_vlog(const char *file, int line, gpr_log_severity severity, strcpy(time_buffer, "error:strftime"); } - flockfile(stderr); - fprintf(stderr, "%s%s.%09d %7ld %s:%d] ", gpr_log_severity_string(severity), - time_buffer, (int)(now.tv_nsec), gettid(), display_file, line); - vfprintf(stderr, format, args); - fputc('\n', stderr); - funlockfile(stderr); + fprintf(stderr, "%s%s.%09d %7ld %s:%d] %s\n", + gpr_log_severity_string(args->severity), time_buffer, + (int)(now.tv_nsec), gettid(), display_file, args->line, + args->message); } #endif diff --git a/src/core/support/log_posix.c b/src/core/support/log_posix.c index b47c433cd71..0420570a3ec 100644 --- a/src/core/support/log_posix.c +++ b/src/core/support/log_posix.c @@ -47,17 +47,40 @@ static long gettid() { return pthread_self(); } -void gpr_vlog(const char *file, int line, gpr_log_severity severity, - const char *format, va_list args) { +void gpr_log(const char *file, int line, gpr_log_severity severity, + const char *format, ...) { + char buf[64]; + char *allocated = NULL; + char *message = NULL; + int ret; + va_list args; + va_start(args, format); + ret = vsnprintf(buf, format, args); + va_end(args); + if (ret < 0) { + message = NULL; + } else if (ret <= sizeof(buf) - 1) { + message = buf; + } else { + message = allocated = gpr_malloc(ret + 1); + va_start(args, format); + vsnprintf(message, format, args); + va_end(args); + } + gpr_log_message(file, line, severity, message); + gpr_free(allocated); +} + +void gpr_default_log(gpr_log_func_args *args) { char *final_slash; const char *display_file; char time_buffer[64]; gpr_timespec now = gpr_now(); struct tm tm; - final_slash = strrchr(file, '/'); + final_slash = strrchr(args->file, '/'); if (final_slash == NULL) - display_file = file; + display_file = args->file; else display_file = final_slash + 1; @@ -68,12 +91,10 @@ void gpr_vlog(const char *file, int line, gpr_log_severity severity, strcpy(time_buffer, "error:strftime"); } - flockfile(stderr); - fprintf(stderr, "%s%s.%09d %7ld %s:%d] ", gpr_log_severity_string(severity), - time_buffer, (int)(now.tv_nsec), gettid(), display_file, line); - vfprintf(stderr, format, args); - fputc('\n', stderr); - funlockfile(stderr); + fprintf(stderr, "%s%s.%09d %7ld %s:%d] %s\n", + gpr_log_severity_string(args->severity), time_buffer, + (int)(now.tv_nsec), gettid(), display_file, args->line, + args->message); } #endif /* defined(GPR_POSIX_LOG) */ diff --git a/src/core/support/log_win32.c b/src/core/support/log_win32.c index e6567dca7e7..ae5f23a90dc 100644 --- a/src/core/support/log_win32.c +++ b/src/core/support/log_win32.c @@ -39,12 +39,42 @@ #include #include +void gpr_log(const char *file, int line, gpr_log_severity severity, + const char *message) { + const char *message = NULL; + va_list args; + int ret; + + /* Determine the length. */ + va_start(args, format); + ret = _vscprintf(format, args); + va_end(args); + if (!(0 <= ret && ret < ~(size_t)0)) { + message = NULL; + } else { + /* Allocate a new buffer, with space for the NUL terminator. */ + strp_buflen = (size_t)ret + 1; + message = gpr_malloc(strp_buflen); + + /* Print to the buffer. */ + va_start(args, format); + ret = vsnprintf_s(message, strp_buflen, _TRUNCATE, format, args); + va_end(args); + if (ret != strp_buflen - 1) { + /* This should never happen. */ + gpr_free(message); + message = NULL; + } + } + + gpr_log_message(file, line, severity, message); + gpr_free(message); +} + /* Simple starter implementation */ -void gpr_vlog(const char *file, int line, gpr_log_severity severity, - const char *format, va_list args) { - fprintf(stderr, "%s %s:%d: ", gpr_log_severity_string(severity), file, line); - vfprintf(stderr, format, args); - fputc('\n', stderr); +void gpr_default_log(gpr_log_func_args *args) { + fprintf(stderr, "%s %s:%d: %s\n", gpr_log_severity_string(severity), + args->file, args->line, args->message); } #endif diff --git a/test/core/support/log_test.c b/test/core/support/log_test.c index fbb7c21ffc3..3ee40b6d76d 100644 --- a/test/core/support/log_test.c +++ b/test/core/support/log_test.c @@ -32,8 +32,17 @@ */ #include + +#include + #include "test/core/util/test_config.h" +static void test_callback(gpr_log_func_args *args) { + GPR_ASSERT(0 == strcmp(__FILE__, args->file)); + GPR_ASSERT(args->severity == GPR_LOG_SEVERITY_INFO); + GPR_ASSERT(0 == strcmp(args->message, "hello 1 2 3")); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); /* test logging at various verbosity levels */ @@ -42,6 +51,9 @@ int main(int argc, char **argv) { gpr_log(GPR_ERROR, "%s", "hello world"); /* should succeed */ GPR_ASSERT(1); + gpr_set_log_function(test_callback); + gpr_log_message(GPR_INFO, "hello 1 2 3"); + gpr_log(GPR_INFO, "hello %d %d %d", 1, 2, 3); /* TODO(ctiller): should we add a GPR_ASSERT failure test here */ return 0; } From 1b151096d1466191bc702aeec3ec76dd2801f38e Mon Sep 17 00:00:00 2001 From: yangg Date: Fri, 9 Jan 2015 15:31:05 -0800 Subject: [PATCH 22/29] Add impl subdirectory under public and move headers that need to be installed to it. Change on 2015/01/09 by yangg ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83640373 --- Makefile | 3 +++ build.json | 6 +++--- .../client => include/grpc++/impl}/internal_stub.h | 6 +++--- {src/cpp => include/grpc++/impl}/rpc_method.h | 10 +++++----- .../grpc++/impl}/rpc_service_method.h | 14 ++++++-------- src/compiler/cpp_generator.cc | 11 +++++------ src/cpp/client/channel.cc | 2 +- src/cpp/client/internal_stub.cc | 2 +- src/cpp/{ => common}/rpc_method.cc | 2 +- src/cpp/server/server.cc | 2 +- src/cpp/server/server_rpc_handler.cc | 2 +- src/cpp/stream/stream_context.cc | 2 +- test/cpp/end2end/end2end_test.cc | 1 - test/cpp/end2end/sync_client_async_server_test.cc | 6 +++--- 14 files changed, 34 insertions(+), 35 deletions(-) rename {src/cpp/client => include/grpc++/impl}/internal_stub.h (92%) rename {src/cpp => include/grpc++/impl}/rpc_method.h (91%) rename {src/cpp/server => include/grpc++/impl}/rpc_service_method.h (96%) rename src/cpp/{ => common}/rpc_method.cc (97%) diff --git a/Makefile b/Makefile index a1c76e155df..ec842cd1e96 100644 --- a/Makefile +++ b/Makefile @@ -1597,6 +1597,9 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/config.h \ include/grpc++/create_channel.h \ include/grpc++/credentials.h \ + include/grpc++/impl/internal_stub.h \ + include/grpc++/impl/rpc_method.h \ + include/grpc++/impl/rpc_service_method.h \ include/grpc++/server_builder.h \ include/grpc++/server_context.h \ include/grpc++/server_credentials.h \ diff --git a/build.json b/build.json index df59c0460ad..d07fd8e783a 100644 --- a/build.json +++ b/build.json @@ -359,6 +359,9 @@ "include/grpc++/config.h", "include/grpc++/create_channel.h", "include/grpc++/credentials.h", + "include/grpc++/impl/internal_stub.h", + "include/grpc++/impl/rpc_method.h", + "include/grpc++/impl/rpc_service_method.h", "include/grpc++/server_builder.h", "include/grpc++/server_context.h", "include/grpc++/server_credentials.h", @@ -369,10 +372,7 @@ ], "headers": [ "src/cpp/client/channel.h", - "src/cpp/client/internal_stub.h", "src/cpp/proto/proto_utils.h", - "src/cpp/rpc_method.h", - "src/cpp/server/rpc_service_method.h", "src/cpp/server/server_rpc_handler.h", "src/cpp/server/thread_pool.h", "src/cpp/stream/stream_context.h", diff --git a/src/cpp/client/internal_stub.h b/include/grpc++/impl/internal_stub.h similarity index 92% rename from src/cpp/client/internal_stub.h rename to include/grpc++/impl/internal_stub.h index 0eaa717d0b6..b32fb3a27c0 100644 --- a/src/cpp/client/internal_stub.h +++ b/include/grpc++/impl/internal_stub.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPCPP_INTERNAL_CLIENT_INTERNAL_STUB_H__ -#define __GRPCPP_INTERNAL_CLIENT_INTERNAL_STUB_H__ +#ifndef __GRPCPP_IMPL_INTERNAL_STUB_H__ +#define __GRPCPP_IMPL_INTERNAL_STUB_H__ #include @@ -57,4 +57,4 @@ class InternalStub { } // namespace grpc -#endif // __GRPCPP_INTERNAL_CLIENT_INTERNAL_STUB_H__ +#endif // __GRPCPP_IMPL_INTERNAL_STUB_H__ diff --git a/src/cpp/rpc_method.h b/include/grpc++/impl/rpc_method.h similarity index 91% rename from src/cpp/rpc_method.h rename to include/grpc++/impl/rpc_method.h index 24a34bed89b..75fec356dd4 100644 --- a/src/cpp/rpc_method.h +++ b/include/grpc++/impl/rpc_method.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPCPP_INTERNAL_RPC_METHOD_H__ -#define __GRPCPP_INTERNAL_RPC_METHOD_H__ +#ifndef __GRPCPP_IMPL_RPC_METHOD_H__ +#define __GRPCPP_IMPL_RPC_METHOD_H__ namespace google { namespace protobuf { @@ -55,15 +55,15 @@ class RpcMethod { : name_(name), method_type_(NORMAL_RPC) {} RpcMethod(const char* name, RpcType type) : name_(name), method_type_(type) {} - const char *name() const { return name_; } + const char* name() const { return name_; } RpcType method_type() const { return method_type_; } private: - const char *name_; + const char* name_; const RpcType method_type_; }; } // namespace grpc -#endif // __GRPCPP_INTERNAL_RPC_METHOD_H__ +#endif // __GRPCPP_IMPL_RPC_METHOD_H__ diff --git a/src/cpp/server/rpc_service_method.h b/include/grpc++/impl/rpc_service_method.h similarity index 96% rename from src/cpp/server/rpc_service_method.h rename to include/grpc++/impl/rpc_service_method.h index f4fe01c06b6..15ff9cab1a4 100644 --- a/src/cpp/server/rpc_service_method.h +++ b/include/grpc++/impl/rpc_service_method.h @@ -31,18 +31,18 @@ * */ -#ifndef __GRPCPP_INTERNAL_SERVER_RPC_SERVICE_METHOD_H__ -#define __GRPCPP_INTERNAL_SERVER_RPC_SERVICE_METHOD_H__ +#ifndef __GRPCPP_IMPL_RPC_SERVICE_METHOD_H__ +#define __GRPCPP_IMPL_RPC_SERVICE_METHOD_H__ #include #include #include #include -#include "src/cpp/rpc_method.h" -#include +#include #include #include +#include namespace grpc { class ServerContext; @@ -200,9 +200,7 @@ class RpcService { methods_.push_back(std::unique_ptr(method)); } - RpcServiceMethod* GetMethod(int i) { - return methods_[i].get(); - } + RpcServiceMethod* GetMethod(int i) { return methods_[i].get(); } int GetMethodCount() const { return methods_.size(); } private: @@ -211,4 +209,4 @@ class RpcService { } // namespace grpc -#endif // __GRPCPP_INTERNAL_SERVER_RPC_SERVICE_METHOD_H__ +#endif // __GRPCPP_IMPL_RPC_SERVICE_METHOD_H__ diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 14d5005dc03..43a04be931d 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -53,8 +53,7 @@ bool ClientOnlyStreaming(const google::protobuf::MethodDescriptor* method) { } bool ServerOnlyStreaming(const google::protobuf::MethodDescriptor* method) { - return !method->client_streaming() && - method->server_streaming(); + return !method->client_streaming() && method->server_streaming(); } bool BidiStreaming(const google::protobuf::MethodDescriptor* method) { @@ -98,7 +97,7 @@ bool HasBidiStreaming(const google::protobuf::FileDescriptor* file) { string GetHeaderIncludes(const google::protobuf::FileDescriptor* file) { string temp = - "#include \"src/cpp/client/internal_stub.h\"\n" + "#include \"grpc++/impl/internal_stub.h\"\n" "#include \"grpc++/status.h\"\n" "\n" "namespace grpc {\n" @@ -126,9 +125,9 @@ string GetHeaderIncludes(const google::protobuf::FileDescriptor* file) { } string GetSourceIncludes() { - return "#include \"src/cpp/rpc_method.h\"\n" - "#include \"src/cpp/server/rpc_service_method.h\"\n" - "#include \"grpc++/channel_interface.h\"\n" + return "#include \"grpc++/channel_interface.h\"\n" + "#include \"grpc++/impl/rpc_method.h\"\n" + "#include \"grpc++/impl/rpc_service_method.h\"\n" "#include \"grpc++/stream.h\"\n"; } diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index 6c8879d5775..bcda4ed40cc 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -41,13 +41,13 @@ #include #include -#include "src/cpp/rpc_method.h" #include "src/cpp/proto/proto_utils.h" #include "src/cpp/stream/stream_context.h" #include #include #include #include +#include #include #include diff --git a/src/cpp/client/internal_stub.cc b/src/cpp/client/internal_stub.cc index ec88ba5e7ed..51cb99d1b49 100644 --- a/src/cpp/client/internal_stub.cc +++ b/src/cpp/client/internal_stub.cc @@ -31,6 +31,6 @@ * */ -#include "src/cpp/client/internal_stub.h" +#include namespace grpc {} // namespace grpc diff --git a/src/cpp/rpc_method.cc b/src/cpp/common/rpc_method.cc similarity index 97% rename from src/cpp/rpc_method.cc rename to src/cpp/common/rpc_method.cc index 8067f42f85e..c8b2ccb10e2 100644 --- a/src/cpp/rpc_method.cc +++ b/src/cpp/common/rpc_method.cc @@ -31,6 +31,6 @@ * */ -#include "src/cpp/rpc_method.h" +#include namespace grpc {} // namespace grpc diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index 2130befa7d5..d85748eea44 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -37,11 +37,11 @@ #include #include #include -#include "src/cpp/server/rpc_service_method.h" #include "src/cpp/server/server_rpc_handler.h" #include "src/cpp/server/thread_pool.h" #include #include +#include #include namespace grpc { diff --git a/src/cpp/server/server_rpc_handler.cc b/src/cpp/server/server_rpc_handler.cc index 3954f04f978..b7b29c24066 100644 --- a/src/cpp/server/server_rpc_handler.cc +++ b/src/cpp/server/server_rpc_handler.cc @@ -34,10 +34,10 @@ #include "src/cpp/server/server_rpc_handler.h" #include -#include "src/cpp/server/rpc_service_method.h" #include "src/cpp/server/server_context_impl.h" #include "src/cpp/stream/stream_context.h" #include +#include namespace grpc { diff --git a/src/cpp/stream/stream_context.cc b/src/cpp/stream/stream_context.cc index b55e647a632..6c424b937ed 100644 --- a/src/cpp/stream/stream_context.cc +++ b/src/cpp/stream/stream_context.cc @@ -34,11 +34,11 @@ #include "src/cpp/stream/stream_context.h" #include -#include "src/cpp/rpc_method.h" #include "src/cpp/proto/proto_utils.h" #include "src/cpp/util/time.h" #include #include +#include #include namespace grpc { diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 1dcdd4202ca..73b7025cb36 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -36,7 +36,6 @@ #include "net/grpc/cpp/echo_duplicate_proto_cc.pb.h" #include "test/cpp/util/echo.pb.h" -#include "src/cpp/server/rpc_service_method.h" #include "src/cpp/util/time.h" #include #include diff --git a/test/cpp/end2end/sync_client_async_server_test.cc b/test/cpp/end2end/sync_client_async_server_test.cc index 839f89cdb1e..f4dad60e223 100644 --- a/test/cpp/end2end/sync_client_async_server_test.cc +++ b/test/cpp/end2end/sync_client_async_server_test.cc @@ -39,17 +39,17 @@ #include #include -#include "src/cpp/client/internal_stub.h" -#include "src/cpp/rpc_method.h" #include "test/cpp/util/echo.pb.h" -#include "net/util/netutil.h" #include #include #include #include +#include +#include #include #include #include "test/cpp/end2end/async_test_server.h" +#include "net/util/netutil.h" #include using grpc::cpp::test::util::EchoRequest; From f31ed60d7c80c6ef4bccd78a292041e2cf2b2575 Mon Sep 17 00:00:00 2001 From: temiola Date: Fri, 9 Jan 2015 15:43:08 -0800 Subject: [PATCH 23/29] Corrects the ruby dockerfile to ensure it has access to git-on-[]. Adds a command for triggering a pull of the latest built docker images. Change on 2015/01/09 by temiola ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83641150 --- tools/dockerfile/grpc_ruby/Dockerfile | 3 +++ tools/gce_setup/grpc_docker.sh | 39 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/tools/dockerfile/grpc_ruby/Dockerfile b/tools/dockerfile/grpc_ruby/Dockerfile index 209257144b7..9aa34bfcc99 100644 --- a/tools/dockerfile/grpc_ruby/Dockerfile +++ b/tools/dockerfile/grpc_ruby/Dockerfile @@ -1,6 +1,9 @@ # Dockerfile for gRPC Ruby FROM grpc/ruby_base +# Start the daemon that allows access to the protected git-on-borg repos +RUN /var/local/git/gcompute-tools/git-cookie-authdaemon + RUN cd /var/local/git/grpc \ && git pull --recurse-submodules \ && git submodule update --init --recursive diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh index 094b97bf3c1..d2614fbb137 100755 --- a/tools/gce_setup/grpc_docker.sh +++ b/tools/gce_setup/grpc_docker.sh @@ -333,6 +333,45 @@ grpc_interop_test_args() { } } +grpc_update_docker_images_args() { + [[ -n $1 ]] && { # host + host=$1 + shift + } || { + echo "$FUNCNAME: missing arg: host" 1>&2 + return 1 + } +} + +# Updates all the known docker images on a host.. +# +# call-seq; +# grpc_update_docker_images +# +# Updates the GCE docker instance +grpc_update_docker_images() { + # declare vars local so that they don't pollute the shell environment + # where they this func is used. + local grpc_zone grpc_project dry_run # set by grpc_set_project_and_zone + # set by grpc_update_docker_images_args + local host + + # set the project zone and check that all necessary args are provided + grpc_set_project_and_zone -f grpc_update_docker_images_args "$@" || return 1 + gce_has_instance $grpc_project $host || return 1; + + local func_lib="/var/local/startup_scripts/shared_startup_funcs.sh" + local cmd="source $func_lib && grpc_docker_pull_known" + local project_opt="--project $grpc_project" + local zone_opt="--zone $grpc_zone" + local ssh_cmd="bash -l -c \"$cmd\"" + echo "will run:" + echo " $ssh_cmd" + echo "on $host" + [[ $dry_run == 1 ]] && return 0 # don't run the command on a dry run + gcloud compute $project_opt ssh $zone_opt $host --command "$cmd" +} + grpc_launch_server_args() { [[ -n $1 ]] && { # host host=$1 From 45fc159eed8d7b9be2277f81e3f43de7e5daabc2 Mon Sep 17 00:00:00 2001 From: nnoble Date: Fri, 9 Jan 2015 18:18:47 -0800 Subject: [PATCH 24/29] Preparing the go plugin for non-[] compilation. Change on 2015/01/09 by nnoble ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83651056 --- Makefile | 34 ++- build.json | 18 ++ src/compiler/go_generator.cc | 520 +++++++++++++++++++++++++++++++++++ src/compiler/go_generator.h | 51 ++++ src/compiler/go_plugin.cc | 83 ++++++ 5 files changed, 702 insertions(+), 4 deletions(-) create mode 100644 src/compiler/go_generator.cc create mode 100644 src/compiler/go_generator.h create mode 100644 src/compiler/go_plugin.cc diff --git a/Makefile b/Makefile index ec842cd1e96..201a10c410f 100644 --- a/Makefile +++ b/Makefile @@ -253,6 +253,7 @@ stop: gen_hpack_tables: bins/$(CONFIG)/gen_hpack_tables cpp_plugin: bins/$(CONFIG)/cpp_plugin ruby_plugin: bins/$(CONFIG)/ruby_plugin +go_plugin: bins/$(CONFIG)/go_plugin grpc_byte_buffer_reader_test: bins/$(CONFIG)/grpc_byte_buffer_reader_test gpr_cancellable_test: bins/$(CONFIG)/gpr_cancellable_test gpr_log_test: bins/$(CONFIG)/gpr_log_test @@ -896,7 +897,7 @@ test_cxx: buildtests_cxx tools: privatelibs bins/$(CONFIG)/gen_hpack_tables bins/$(CONFIG)/grpc_fetch_oauth2 -protoc_plugins: bins/$(CONFIG)/cpp_plugin bins/$(CONFIG)/ruby_plugin +protoc_plugins: bins/$(CONFIG)/cpp_plugin bins/$(CONFIG)/ruby_plugin bins/$(CONFIG)/go_plugin buildbenchmarks: privatelibs bins/$(CONFIG)/grpc_completion_queue_benchmark bins/$(CONFIG)/low_level_ping_pong_benchmark @@ -1025,7 +1026,7 @@ bins_dep_c: deps_gen_hpack_tables deps_grpc_byte_buffer_reader_test deps_gpr_can dep_cxx: deps_libgrpc++ deps_libgrpc++_test_util -bins_dep_cxx: deps_cpp_plugin deps_ruby_plugin deps_thread_pool_test deps_status_test deps_sync_client_async_server_test deps_qps_client deps_qps_server deps_interop_server deps_interop_client deps_end2end_test deps_channel_arguments_test deps_credentials_test +bins_dep_cxx: deps_cpp_plugin deps_ruby_plugin deps_go_plugin deps_thread_pool_test deps_status_test deps_sync_client_async_server_test deps_qps_client deps_qps_server deps_interop_server deps_interop_client deps_end2end_test deps_channel_arguments_test deps_credentials_test install: install_c install_cxx @@ -1115,7 +1116,7 @@ ifneq ($(SYSTEM),Darwin) endif endif -clean: clean_libgpr clean_libgrpc clean_libgrpc_unsecure clean_libgrpc_test_util clean_libgrpc++ clean_libgrpc++_test_util clean_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_census_simple_request clean_libend2end_test_disappearing_server clean_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_invoke_large_request clean_libend2end_test_max_concurrent_streams clean_libend2end_test_no_op clean_libend2end_test_ping_pong_streaming clean_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_simple_delayed_request clean_libend2end_test_simple_request clean_libend2end_test_thread_stress clean_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_certs clean_gen_hpack_tables clean_cpp_plugin clean_ruby_plugin clean_grpc_byte_buffer_reader_test clean_gpr_cancellable_test clean_gpr_log_test clean_gpr_useful_test clean_gpr_cmdline_test clean_gpr_histogram_test clean_gpr_host_port_test clean_gpr_slice_buffer_test clean_gpr_slice_test clean_gpr_string_test clean_gpr_sync_test clean_gpr_thd_test clean_gpr_time_test clean_murmur_hash_test clean_grpc_stream_op_test clean_alpn_test clean_time_averaged_stats_test clean_chttp2_stream_encoder_test clean_hpack_table_test clean_chttp2_stream_map_test clean_hpack_parser_test clean_transport_metadata_test clean_chttp2_status_conversion_test clean_chttp2_transport_end2end_test clean_tcp_posix_test clean_dualstack_socket_test clean_no_server_test clean_resolve_address_test clean_sockaddr_utils_test clean_tcp_server_posix_test clean_tcp_client_posix_test clean_grpc_channel_stack_test clean_metadata_buffer_test clean_grpc_completion_queue_test clean_grpc_completion_queue_benchmark clean_census_trace_store_test clean_census_stats_store_test clean_census_window_stats_test clean_census_statistics_quick_test clean_census_statistics_small_log_test clean_census_statistics_performance_test clean_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_circular_buffer_test clean_census_stub_test clean_census_hash_table_test clean_fling_server clean_fling_client clean_fling_test clean_echo_server clean_echo_client clean_echo_test clean_low_level_ping_pong_benchmark clean_message_compress_test clean_bin_encoder_test clean_secure_endpoint_test clean_httpcli_format_request_test clean_httpcli_parser_test clean_httpcli_test clean_grpc_credentials_test clean_grpc_fetch_oauth2 clean_grpc_base64_test clean_grpc_json_token_test clean_timeout_encoding_test clean_fd_posix_test clean_fling_stream_test clean_lame_client_test clean_thread_pool_test clean_status_test clean_sync_client_async_server_test clean_qps_client clean_qps_server clean_interop_server clean_interop_client clean_end2end_test clean_channel_arguments_test clean_credentials_test clean_alarm_test clean_alarm_list_test clean_alarm_heap_test clean_time_test clean_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_no_op_test clean_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_no_op_test clean_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +clean: clean_libgpr clean_libgrpc clean_libgrpc_unsecure clean_libgrpc_test_util clean_libgrpc++ clean_libgrpc++_test_util clean_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_census_simple_request clean_libend2end_test_disappearing_server clean_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_invoke_large_request clean_libend2end_test_max_concurrent_streams clean_libend2end_test_no_op clean_libend2end_test_ping_pong_streaming clean_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_simple_delayed_request clean_libend2end_test_simple_request clean_libend2end_test_thread_stress clean_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_certs clean_gen_hpack_tables clean_cpp_plugin clean_ruby_plugin clean_go_plugin clean_grpc_byte_buffer_reader_test clean_gpr_cancellable_test clean_gpr_log_test clean_gpr_useful_test clean_gpr_cmdline_test clean_gpr_histogram_test clean_gpr_host_port_test clean_gpr_slice_buffer_test clean_gpr_slice_test clean_gpr_string_test clean_gpr_sync_test clean_gpr_thd_test clean_gpr_time_test clean_murmur_hash_test clean_grpc_stream_op_test clean_alpn_test clean_time_averaged_stats_test clean_chttp2_stream_encoder_test clean_hpack_table_test clean_chttp2_stream_map_test clean_hpack_parser_test clean_transport_metadata_test clean_chttp2_status_conversion_test clean_chttp2_transport_end2end_test clean_tcp_posix_test clean_dualstack_socket_test clean_no_server_test clean_resolve_address_test clean_sockaddr_utils_test clean_tcp_server_posix_test clean_tcp_client_posix_test clean_grpc_channel_stack_test clean_metadata_buffer_test clean_grpc_completion_queue_test clean_grpc_completion_queue_benchmark clean_census_trace_store_test clean_census_stats_store_test clean_census_window_stats_test clean_census_statistics_quick_test clean_census_statistics_small_log_test clean_census_statistics_performance_test clean_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_circular_buffer_test clean_census_stub_test clean_census_hash_table_test clean_fling_server clean_fling_client clean_fling_test clean_echo_server clean_echo_client clean_echo_test clean_low_level_ping_pong_benchmark clean_message_compress_test clean_bin_encoder_test clean_secure_endpoint_test clean_httpcli_format_request_test clean_httpcli_parser_test clean_httpcli_test clean_grpc_credentials_test clean_grpc_fetch_oauth2 clean_grpc_base64_test clean_grpc_json_token_test clean_timeout_encoding_test clean_fd_posix_test clean_fling_stream_test clean_lame_client_test clean_thread_pool_test clean_status_test clean_sync_client_async_server_test clean_qps_client clean_qps_server clean_interop_server clean_interop_client clean_end2end_test clean_channel_arguments_test clean_credentials_test clean_alarm_test clean_alarm_list_test clean_alarm_heap_test clean_time_test clean_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_no_op_test clean_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_no_op_test clean_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(Q) $(RM) -r deps objs libs bins gens @@ -2719,6 +2720,31 @@ clean_ruby_plugin: $(Q) $(RM) bins/$(CONFIG)/ruby_plugin +GO_PLUGIN_SRC = \ + src/compiler/go_plugin.cpp \ + src/compiler/go_generator.cpp \ + +GO_PLUGIN_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(GO_PLUGIN_SRC)))) +GO_PLUGIN_DEPS = $(addprefix deps/$(CONFIG)/, $(addsuffix .dep, $(basename $(GO_PLUGIN_SRC)))) + +bins/$(CONFIG)/go_plugin: $(GO_PLUGIN_OBJS) + $(E) "[HOSTLD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GO_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o bins/$(CONFIG)/go_plugin + +deps_go_plugin: $(GO_PLUGIN_DEPS) + +ifneq ($(NO_DEPS),true) +-include $(GO_PLUGIN_DEPS) +endif + +clean_go_plugin: + $(E) "[CLEAN] Cleaning go_plugin files" + $(Q) $(RM) $(GO_PLUGIN_OBJS) + $(Q) $(RM) $(GO_PLUGIN_DEPS) + $(Q) $(RM) bins/$(CONFIG)/go_plugin + + GRPC_BYTE_BUFFER_READER_TEST_SRC = \ test/core/surface/byte_buffer_reader_test.c \ @@ -9613,4 +9639,4 @@ clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_ -.PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx clean dep_c dep_cxx bins_dep_c bins_dep_cxx deps_libgpr clean_libgpr deps_libgrpc clean_libgrpc deps_libgrpc_unsecure clean_libgrpc_unsecure deps_libgrpc_test_util clean_libgrpc_test_util deps_libgrpc++ clean_libgrpc++ deps_libgrpc++_test_util clean_libgrpc++_test_util deps_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_census_simple_request clean_libend2end_test_census_simple_request deps_libend2end_test_disappearing_server clean_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request clean_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams clean_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op clean_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming clean_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request clean_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request clean_libend2end_test_simple_request deps_libend2end_test_thread_stress clean_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs clean_libend2end_certs deps_gen_hpack_tables clean_gen_hpack_tables deps_cpp_plugin clean_cpp_plugin deps_ruby_plugin clean_ruby_plugin deps_grpc_byte_buffer_reader_test clean_grpc_byte_buffer_reader_test deps_gpr_cancellable_test clean_gpr_cancellable_test deps_gpr_log_test clean_gpr_log_test deps_gpr_useful_test clean_gpr_useful_test deps_gpr_cmdline_test clean_gpr_cmdline_test deps_gpr_histogram_test clean_gpr_histogram_test deps_gpr_host_port_test clean_gpr_host_port_test deps_gpr_slice_buffer_test clean_gpr_slice_buffer_test deps_gpr_slice_test clean_gpr_slice_test deps_gpr_string_test clean_gpr_string_test deps_gpr_sync_test clean_gpr_sync_test deps_gpr_thd_test clean_gpr_thd_test deps_gpr_time_test clean_gpr_time_test deps_murmur_hash_test clean_murmur_hash_test deps_grpc_stream_op_test clean_grpc_stream_op_test deps_alpn_test clean_alpn_test deps_time_averaged_stats_test clean_time_averaged_stats_test deps_chttp2_stream_encoder_test clean_chttp2_stream_encoder_test deps_hpack_table_test clean_hpack_table_test deps_chttp2_stream_map_test clean_chttp2_stream_map_test deps_hpack_parser_test clean_hpack_parser_test deps_transport_metadata_test clean_transport_metadata_test deps_chttp2_status_conversion_test clean_chttp2_status_conversion_test deps_chttp2_transport_end2end_test clean_chttp2_transport_end2end_test deps_tcp_posix_test clean_tcp_posix_test deps_dualstack_socket_test clean_dualstack_socket_test deps_no_server_test clean_no_server_test deps_resolve_address_test clean_resolve_address_test deps_sockaddr_utils_test clean_sockaddr_utils_test deps_tcp_server_posix_test clean_tcp_server_posix_test deps_tcp_client_posix_test clean_tcp_client_posix_test deps_grpc_channel_stack_test clean_grpc_channel_stack_test deps_metadata_buffer_test clean_metadata_buffer_test deps_grpc_completion_queue_test clean_grpc_completion_queue_test deps_grpc_completion_queue_benchmark clean_grpc_completion_queue_benchmark deps_census_trace_store_test clean_census_trace_store_test deps_census_stats_store_test clean_census_stats_store_test deps_census_window_stats_test clean_census_window_stats_test deps_census_statistics_quick_test clean_census_statistics_quick_test deps_census_statistics_small_log_test clean_census_statistics_small_log_test deps_census_statistics_performance_test clean_census_statistics_performance_test deps_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test clean_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test clean_census_stub_test deps_census_hash_table_test clean_census_hash_table_test deps_fling_server clean_fling_server deps_fling_client clean_fling_client deps_fling_test clean_fling_test deps_echo_server clean_echo_server deps_echo_client clean_echo_client deps_echo_test clean_echo_test deps_low_level_ping_pong_benchmark clean_low_level_ping_pong_benchmark deps_message_compress_test clean_message_compress_test deps_bin_encoder_test clean_bin_encoder_test deps_secure_endpoint_test clean_secure_endpoint_test deps_httpcli_format_request_test clean_httpcli_format_request_test deps_httpcli_parser_test clean_httpcli_parser_test deps_httpcli_test clean_httpcli_test deps_grpc_credentials_test clean_grpc_credentials_test deps_grpc_fetch_oauth2 clean_grpc_fetch_oauth2 deps_grpc_base64_test clean_grpc_base64_test deps_grpc_json_token_test clean_grpc_json_token_test deps_timeout_encoding_test clean_timeout_encoding_test deps_fd_posix_test clean_fd_posix_test deps_fling_stream_test clean_fling_stream_test deps_lame_client_test clean_lame_client_test deps_thread_pool_test clean_thread_pool_test deps_status_test clean_status_test deps_sync_client_async_server_test clean_sync_client_async_server_test deps_qps_client clean_qps_client deps_qps_server clean_qps_server deps_interop_server clean_interop_server deps_interop_client clean_interop_client deps_end2end_test clean_end2end_test deps_channel_arguments_test clean_channel_arguments_test deps_credentials_test clean_credentials_test deps_alarm_test clean_alarm_test deps_alarm_list_test clean_alarm_list_test deps_alarm_heap_test clean_alarm_heap_test deps_time_test clean_time_test deps_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_census_simple_request_test deps_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test clean_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_census_simple_request_test deps_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test clean_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_census_simple_request_test deps_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +.PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx clean dep_c dep_cxx bins_dep_c bins_dep_cxx deps_libgpr clean_libgpr deps_libgrpc clean_libgrpc deps_libgrpc_unsecure clean_libgrpc_unsecure deps_libgrpc_test_util clean_libgrpc_test_util deps_libgrpc++ clean_libgrpc++ deps_libgrpc++_test_util clean_libgrpc++_test_util deps_libend2end_fixture_chttp2_fake_security clean_libend2end_fixture_chttp2_fake_security deps_libend2end_fixture_chttp2_fullstack clean_libend2end_fixture_chttp2_fullstack deps_libend2end_fixture_chttp2_simple_ssl_fullstack clean_libend2end_fixture_chttp2_simple_ssl_fullstack deps_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack clean_libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack deps_libend2end_fixture_chttp2_socket_pair clean_libend2end_fixture_chttp2_socket_pair deps_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time clean_libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time deps_libend2end_test_cancel_after_accept clean_libend2end_test_cancel_after_accept deps_libend2end_test_cancel_after_accept_and_writes_closed clean_libend2end_test_cancel_after_accept_and_writes_closed deps_libend2end_test_cancel_after_invoke clean_libend2end_test_cancel_after_invoke deps_libend2end_test_cancel_before_invoke clean_libend2end_test_cancel_before_invoke deps_libend2end_test_cancel_in_a_vacuum clean_libend2end_test_cancel_in_a_vacuum deps_libend2end_test_census_simple_request clean_libend2end_test_census_simple_request deps_libend2end_test_disappearing_server clean_libend2end_test_disappearing_server deps_libend2end_test_early_server_shutdown_finishes_inflight_calls clean_libend2end_test_early_server_shutdown_finishes_inflight_calls deps_libend2end_test_early_server_shutdown_finishes_tags clean_libend2end_test_early_server_shutdown_finishes_tags deps_libend2end_test_invoke_large_request clean_libend2end_test_invoke_large_request deps_libend2end_test_max_concurrent_streams clean_libend2end_test_max_concurrent_streams deps_libend2end_test_no_op clean_libend2end_test_no_op deps_libend2end_test_ping_pong_streaming clean_libend2end_test_ping_pong_streaming deps_libend2end_test_request_response_with_binary_metadata_and_payload clean_libend2end_test_request_response_with_binary_metadata_and_payload deps_libend2end_test_request_response_with_metadata_and_payload clean_libend2end_test_request_response_with_metadata_and_payload deps_libend2end_test_request_response_with_payload clean_libend2end_test_request_response_with_payload deps_libend2end_test_request_response_with_trailing_metadata_and_payload clean_libend2end_test_request_response_with_trailing_metadata_and_payload deps_libend2end_test_simple_delayed_request clean_libend2end_test_simple_delayed_request deps_libend2end_test_simple_request clean_libend2end_test_simple_request deps_libend2end_test_thread_stress clean_libend2end_test_thread_stress deps_libend2end_test_writes_done_hangs_with_pending_read clean_libend2end_test_writes_done_hangs_with_pending_read deps_libend2end_certs clean_libend2end_certs deps_gen_hpack_tables clean_gen_hpack_tables deps_cpp_plugin clean_cpp_plugin deps_ruby_plugin clean_ruby_plugin deps_go_plugin clean_go_plugin deps_grpc_byte_buffer_reader_test clean_grpc_byte_buffer_reader_test deps_gpr_cancellable_test clean_gpr_cancellable_test deps_gpr_log_test clean_gpr_log_test deps_gpr_useful_test clean_gpr_useful_test deps_gpr_cmdline_test clean_gpr_cmdline_test deps_gpr_histogram_test clean_gpr_histogram_test deps_gpr_host_port_test clean_gpr_host_port_test deps_gpr_slice_buffer_test clean_gpr_slice_buffer_test deps_gpr_slice_test clean_gpr_slice_test deps_gpr_string_test clean_gpr_string_test deps_gpr_sync_test clean_gpr_sync_test deps_gpr_thd_test clean_gpr_thd_test deps_gpr_time_test clean_gpr_time_test deps_murmur_hash_test clean_murmur_hash_test deps_grpc_stream_op_test clean_grpc_stream_op_test deps_alpn_test clean_alpn_test deps_time_averaged_stats_test clean_time_averaged_stats_test deps_chttp2_stream_encoder_test clean_chttp2_stream_encoder_test deps_hpack_table_test clean_hpack_table_test deps_chttp2_stream_map_test clean_chttp2_stream_map_test deps_hpack_parser_test clean_hpack_parser_test deps_transport_metadata_test clean_transport_metadata_test deps_chttp2_status_conversion_test clean_chttp2_status_conversion_test deps_chttp2_transport_end2end_test clean_chttp2_transport_end2end_test deps_tcp_posix_test clean_tcp_posix_test deps_dualstack_socket_test clean_dualstack_socket_test deps_no_server_test clean_no_server_test deps_resolve_address_test clean_resolve_address_test deps_sockaddr_utils_test clean_sockaddr_utils_test deps_tcp_server_posix_test clean_tcp_server_posix_test deps_tcp_client_posix_test clean_tcp_client_posix_test deps_grpc_channel_stack_test clean_grpc_channel_stack_test deps_metadata_buffer_test clean_metadata_buffer_test deps_grpc_completion_queue_test clean_grpc_completion_queue_test deps_grpc_completion_queue_benchmark clean_grpc_completion_queue_benchmark deps_census_trace_store_test clean_census_trace_store_test deps_census_stats_store_test clean_census_stats_store_test deps_census_window_stats_test clean_census_window_stats_test deps_census_statistics_quick_test clean_census_statistics_quick_test deps_census_statistics_small_log_test clean_census_statistics_small_log_test deps_census_statistics_performance_test clean_census_statistics_performance_test deps_census_statistics_multiple_writers_test clean_census_statistics_multiple_writers_test deps_census_statistics_multiple_writers_circular_buffer_test clean_census_statistics_multiple_writers_circular_buffer_test deps_census_stub_test clean_census_stub_test deps_census_hash_table_test clean_census_hash_table_test deps_fling_server clean_fling_server deps_fling_client clean_fling_client deps_fling_test clean_fling_test deps_echo_server clean_echo_server deps_echo_client clean_echo_client deps_echo_test clean_echo_test deps_low_level_ping_pong_benchmark clean_low_level_ping_pong_benchmark deps_message_compress_test clean_message_compress_test deps_bin_encoder_test clean_bin_encoder_test deps_secure_endpoint_test clean_secure_endpoint_test deps_httpcli_format_request_test clean_httpcli_format_request_test deps_httpcli_parser_test clean_httpcli_parser_test deps_httpcli_test clean_httpcli_test deps_grpc_credentials_test clean_grpc_credentials_test deps_grpc_fetch_oauth2 clean_grpc_fetch_oauth2 deps_grpc_base64_test clean_grpc_base64_test deps_grpc_json_token_test clean_grpc_json_token_test deps_timeout_encoding_test clean_timeout_encoding_test deps_fd_posix_test clean_fd_posix_test deps_fling_stream_test clean_fling_stream_test deps_lame_client_test clean_lame_client_test deps_thread_pool_test clean_thread_pool_test deps_status_test clean_status_test deps_sync_client_async_server_test clean_sync_client_async_server_test deps_qps_client clean_qps_client deps_qps_server clean_qps_server deps_interop_server clean_interop_server deps_interop_client clean_interop_client deps_end2end_test clean_end2end_test deps_channel_arguments_test clean_channel_arguments_test deps_credentials_test clean_credentials_test deps_alarm_test clean_alarm_test deps_alarm_list_test clean_alarm_list_test deps_alarm_heap_test clean_alarm_heap_test deps_time_test clean_time_test deps_chttp2_fake_security_cancel_after_accept_test clean_chttp2_fake_security_cancel_after_accept_test deps_chttp2_fake_security_cancel_after_accept_and_writes_closed_test clean_chttp2_fake_security_cancel_after_accept_and_writes_closed_test deps_chttp2_fake_security_cancel_after_invoke_test clean_chttp2_fake_security_cancel_after_invoke_test deps_chttp2_fake_security_cancel_before_invoke_test clean_chttp2_fake_security_cancel_before_invoke_test deps_chttp2_fake_security_cancel_in_a_vacuum_test clean_chttp2_fake_security_cancel_in_a_vacuum_test deps_chttp2_fake_security_census_simple_request_test clean_chttp2_fake_security_census_simple_request_test deps_chttp2_fake_security_disappearing_server_test clean_chttp2_fake_security_disappearing_server_test deps_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fake_security_early_server_shutdown_finishes_tags_test clean_chttp2_fake_security_early_server_shutdown_finishes_tags_test deps_chttp2_fake_security_invoke_large_request_test clean_chttp2_fake_security_invoke_large_request_test deps_chttp2_fake_security_max_concurrent_streams_test clean_chttp2_fake_security_max_concurrent_streams_test deps_chttp2_fake_security_no_op_test clean_chttp2_fake_security_no_op_test deps_chttp2_fake_security_ping_pong_streaming_test clean_chttp2_fake_security_ping_pong_streaming_test deps_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_binary_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_metadata_and_payload_test deps_chttp2_fake_security_request_response_with_payload_test clean_chttp2_fake_security_request_response_with_payload_test deps_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fake_security_simple_delayed_request_test clean_chttp2_fake_security_simple_delayed_request_test deps_chttp2_fake_security_simple_request_test clean_chttp2_fake_security_simple_request_test deps_chttp2_fake_security_thread_stress_test clean_chttp2_fake_security_thread_stress_test deps_chttp2_fake_security_writes_done_hangs_with_pending_read_test clean_chttp2_fake_security_writes_done_hangs_with_pending_read_test deps_chttp2_fullstack_cancel_after_accept_test clean_chttp2_fullstack_cancel_after_accept_test deps_chttp2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_fullstack_cancel_after_invoke_test clean_chttp2_fullstack_cancel_after_invoke_test deps_chttp2_fullstack_cancel_before_invoke_test clean_chttp2_fullstack_cancel_before_invoke_test deps_chttp2_fullstack_cancel_in_a_vacuum_test clean_chttp2_fullstack_cancel_in_a_vacuum_test deps_chttp2_fullstack_census_simple_request_test clean_chttp2_fullstack_census_simple_request_test deps_chttp2_fullstack_disappearing_server_test clean_chttp2_fullstack_disappearing_server_test deps_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_fullstack_invoke_large_request_test clean_chttp2_fullstack_invoke_large_request_test deps_chttp2_fullstack_max_concurrent_streams_test clean_chttp2_fullstack_max_concurrent_streams_test deps_chttp2_fullstack_no_op_test clean_chttp2_fullstack_no_op_test deps_chttp2_fullstack_ping_pong_streaming_test clean_chttp2_fullstack_ping_pong_streaming_test deps_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_fullstack_request_response_with_payload_test clean_chttp2_fullstack_request_response_with_payload_test deps_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_fullstack_simple_delayed_request_test clean_chttp2_fullstack_simple_delayed_request_test deps_chttp2_fullstack_simple_request_test clean_chttp2_fullstack_simple_request_test deps_chttp2_fullstack_thread_stress_test clean_chttp2_fullstack_thread_stress_test deps_chttp2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_fullstack_census_simple_request_test clean_chttp2_simple_ssl_fullstack_census_simple_request_test deps_chttp2_simple_ssl_fullstack_disappearing_server_test clean_chttp2_simple_ssl_fullstack_disappearing_server_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_fullstack_no_op_test clean_chttp2_simple_ssl_fullstack_no_op_test deps_chttp2_simple_ssl_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_fullstack_simple_request_test clean_chttp2_simple_ssl_fullstack_simple_request_test deps_chttp2_simple_ssl_fullstack_thread_stress_test clean_chttp2_simple_ssl_fullstack_thread_stress_test deps_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test deps_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test clean_chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test deps_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test clean_chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test clean_chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test deps_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test clean_chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test deps_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test clean_chttp2_simple_ssl_with_oauth2_fullstack_no_op_test deps_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test clean_chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test clean_chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test clean_chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test deps_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test clean_chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test deps_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test clean_chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_cancel_after_accept_test clean_chttp2_socket_pair_cancel_after_accept_test deps_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_cancel_after_invoke_test clean_chttp2_socket_pair_cancel_after_invoke_test deps_chttp2_socket_pair_cancel_before_invoke_test clean_chttp2_socket_pair_cancel_before_invoke_test deps_chttp2_socket_pair_cancel_in_a_vacuum_test clean_chttp2_socket_pair_cancel_in_a_vacuum_test deps_chttp2_socket_pair_census_simple_request_test clean_chttp2_socket_pair_census_simple_request_test deps_chttp2_socket_pair_disappearing_server_test clean_chttp2_socket_pair_disappearing_server_test deps_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_invoke_large_request_test clean_chttp2_socket_pair_invoke_large_request_test deps_chttp2_socket_pair_max_concurrent_streams_test clean_chttp2_socket_pair_max_concurrent_streams_test deps_chttp2_socket_pair_no_op_test clean_chttp2_socket_pair_no_op_test deps_chttp2_socket_pair_ping_pong_streaming_test clean_chttp2_socket_pair_ping_pong_streaming_test deps_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_request_response_with_payload_test clean_chttp2_socket_pair_request_response_with_payload_test deps_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_simple_delayed_request_test clean_chttp2_socket_pair_simple_delayed_request_test deps_chttp2_socket_pair_simple_request_test clean_chttp2_socket_pair_simple_request_test deps_chttp2_socket_pair_thread_stress_test clean_chttp2_socket_pair_thread_stress_test deps_chttp2_socket_pair_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_writes_done_hangs_with_pending_read_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test deps_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test clean_chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test deps_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test clean_chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test deps_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test clean_chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test deps_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test clean_chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test deps_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test clean_chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test deps_chttp2_socket_pair_one_byte_at_a_time_no_op_test clean_chttp2_socket_pair_one_byte_at_a_time_no_op_test deps_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test clean_chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test clean_chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test deps_chttp2_socket_pair_one_byte_at_a_time_simple_request_test clean_chttp2_socket_pair_one_byte_at_a_time_simple_request_test deps_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test clean_chttp2_socket_pair_one_byte_at_a_time_thread_stress_test deps_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test clean_chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test diff --git a/build.json b/build.json index d07fd8e783a..968c1dfadec 100644 --- a/build.json +++ b/build.json @@ -442,6 +442,24 @@ "deps": [] }, + { + "name": "go_plugin", + "build": "protoc", + "c++": true, + "secure": false, + "src": [ + "src/compiler/go_plugin.cpp", + "src/compiler/go_generator.cpp" + ], + "headers": [ + "src/compiler/go_generator.h", + "src/compiler/go_generator_helpers-inl.h", + "src/compiler/go_generator_map-inl.h", + "src/compiler/go_generator_string-inl.h" + ], + "deps": [] + }, + { "name": "grpc_byte_buffer_reader_test", "build": "test", diff --git a/src/compiler/go_generator.cc b/src/compiler/go_generator.cc new file mode 100644 index 00000000000..8beae8dcccf --- /dev/null +++ b/src/compiler/go_generator.cc @@ -0,0 +1,520 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +using namespace std; + +#include "src/compiler/go_generator.h" + +#include + +#include +#include +#include +#include + +namespace grpc_go_generator { + +bool NoStreaming(const google::protobuf::MethodDescriptor* method) { + return !method->client_streaming() && + !method->server_streaming(); +} + +bool ClientOnlyStreaming(const google::protobuf::MethodDescriptor* method) { + return method->client_streaming() && + !method->server_streaming(); +} + +bool ServerOnlyStreaming(const google::protobuf::MethodDescriptor* method) { + return !method->client_streaming() && + method->server_streaming(); +} + +bool BidiStreaming(const google::protobuf::MethodDescriptor* method) { + return method->client_streaming() && + method->server_streaming(); +} + +bool HasClientOnlyStreaming(const google::protobuf::FileDescriptor* file) { + for (int i = 0; i < file->service_count(); i++) { + for (int j = 0; j < file->service(i)->method_count(); j++) { + if (ClientOnlyStreaming(file->service(i)->method(j))) { + return true; + } + } + } + return false; +} + +string LowerCaseService(const string& service) { + string ret = service; + if (!ret.empty() && ret[0] >= 'A' && ret[0] <= 'Z') { + ret[0] = ret[0] - 'A' + 'a'; + } + return ret; +} + +void PrintClientMethodDef(google::protobuf::io::Printer* printer, + const google::protobuf::MethodDescriptor* method, + map* vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type()->name(); + (*vars)["Response"] = method->output_type()->name(); + if (NoStreaming(method)) { + printer->Print(*vars, + "\t$Method$(ctx context.Context, in *$Request$, opts ...rpc.CallOption) " + "(*$Response$, error)\n"); + } else if (BidiStreaming(method)) { + printer->Print(*vars, + "\t$Method$(ctx context.Context, opts ...rpc.CallOption) " + "($Service$_$Method$Client, error)\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print(*vars, + "\t$Method$(ctx context.Context, m *$Request$, opts ...rpc.CallOption) " + "($Service$_$Method$Client, error)\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print(*vars, + "\t$Method$(ctx context.Context, opts ...rpc.CallOption) " + "($Service$_$Method$Client, error)\n"); + } +} + +void PrintClientMethodImpl(google::protobuf::io::Printer* printer, + const google::protobuf::MethodDescriptor* method, + map* vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type()->name(); + (*vars)["Response"] = method->output_type()->name(); + + if (NoStreaming(method)) { + printer->Print(*vars, + "func (c *$ServiceStruct$Client) $Method$(ctx context.Context, " + "in *$Request$, opts ...rpc.CallOption) (*$Response$, error) {\n"); + printer->Print(*vars, + "\tout := new($Response$)\n"); + printer->Print(*vars, + "\terr := rpc.Invoke(ctx, \"/$Package$$Service$/$Method$\", " + "in, out, c.cc, opts...)\n"); + printer->Print("\tif err != nil {\n"); + printer->Print("\t\treturn nil, err\n"); + printer->Print("\t}\n"); + printer->Print("\treturn out, nil\n"); + printer->Print("}\n\n"); + } else if (BidiStreaming(method)) { + printer->Print( + *vars, + "func (c *$ServiceStruct$Client) $Method$(ctx context.Context, opts " + "...rpc.CallOption) ($Service$_$Method$Client, error) {\n" + "\tstream, err := rpc.NewClientStream(ctx, c.cc, " + "\"/$Package$$Service$/$Method$\", opts...)\n" + "\tif err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\treturn &$ServiceStruct$$Method$Client{stream}, nil\n" + "}\n\n"); + printer->Print(*vars, + "type $Service$_$Method$Client interface {\n" + "\tSend(*$Request$) error\n" + "\tRecv() (*$Response$, error)\n" + "\trpc.ClientStream\n" + "}\n\n"); + printer->Print(*vars, + "type $ServiceStruct$$Method$Client struct {\n" + "\trpc.ClientStream\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Client) Send(m *$Request$) error {\n" + "\treturn x.ClientStream.SendProto(m)\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Client) Recv() (*$Response$, error) " + "{\n" + "\tm := new($Response$)\n" + "\tif err := x.ClientStream.RecvProto(m); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\treturn m, nil\n" + "}\n\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print( + *vars, + "func (c *$ServiceStruct$Client) $Method$(ctx context.Context, m " + "*$Request$, " + "opts ...rpc.CallOption) ($Service$_$Method$Client, error) {\n" + "\tstream, err := rpc.NewClientStream(ctx, c.cc, " + "\"/$Package$$Service$/$Method$\", opts...)\n" + "\tif err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\tx := &$ServiceStruct$$Method$Client{stream}\n" + "\tif err := x.ClientStream.SendProto(m); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\tif err := x.ClientStream.CloseSend(); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\treturn x, nil\n" + "}\n\n"); + printer->Print(*vars, + "type $Service$_$Method$Client interface {\n" + "\tRecv() (*$Response$, error)\n" + "\trpc.ClientStream\n" + "}\n\n"); + printer->Print(*vars, + "type $ServiceStruct$$Method$Client struct {\n" + "\trpc.ClientStream\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Client) Recv() (*$Response$, error) " + "{\n" + "\tm := new($Response$)\n" + "\tif err := x.ClientStream.RecvProto(m); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\treturn m, nil\n" + "}\n\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print( + *vars, + "func (c *$ServiceStruct$Client) $Method$(ctx context.Context, opts " + "...rpc.CallOption) ($Service$_$Method$Client, error) {\n" + "\tstream, err := rpc.NewClientStream(ctx, c.cc, " + "\"/$Package$$Service$/$Method$\", opts...)\n" + "\tif err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\treturn &$ServiceStruct$$Method$Client{stream}, nil\n" + "}\n\n"); + printer->Print(*vars, + "type $Service$_$Method$Client interface {\n" + "\tSend(*$Request$) error\n" + "\tCloseAndRecv() (*$Response$, error)\n" + "\trpc.ClientStream\n" + "}\n\n"); + printer->Print(*vars, + "type $ServiceStruct$$Method$Client struct {\n" + "\trpc.ClientStream\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Client) Send(m *$Request$) error {\n" + "\treturn x.ClientStream.SendProto(m)\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Client) CloseAndRecv() (*$Response$, " + "error) {\n" + "\tif err := x.ClientStream.CloseSend(); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\tm := new($Response$)\n" + "\tif err := x.ClientStream.RecvProto(m); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\t// Read EOF.\n" + "\tif err := x.ClientStream.RecvProto(m); err == io.EOF {\n" + "\t\treturn m, io.EOF\n" + "\t}\n" + "\t// gRPC protocol violation.\n" + "\treturn m, fmt.Errorf(\"Violate gRPC client streaming protocol: no " + "EOF after the response.\")\n" + "}\n\n"); + } +} + +void PrintClient(google::protobuf::io::Printer* printer, + const google::protobuf::ServiceDescriptor* service, + map* vars) { + (*vars)["Service"] = service->name(); + (*vars)["ServiceStruct"] = LowerCaseService(service->name()); + printer->Print(*vars, "type $Service$Client interface {\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintClientMethodDef(printer, service->method(i), vars); + } + printer->Print("}\n\n"); + + printer->Print(*vars, + "type $ServiceStruct$Client struct {\n" + "\tcc *rpc.ClientConn\n" + "}\n\n"); + printer->Print(*vars, + "func New$Service$Client(cc *rpc.ClientConn) $Service$Client {\n" + "\treturn &$ServiceStruct$Client{cc}\n" + "}\n\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintClientMethodImpl(printer, service->method(i), vars); + } +} + +void PrintServerMethodDef(google::protobuf::io::Printer* printer, + const google::protobuf::MethodDescriptor* method, + map* vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type()->name(); + (*vars)["Response"] = method->output_type()->name(); + if (NoStreaming(method)) { + printer->Print(*vars, + "\t$Method$(context.Context, *$Request$) (*$Response$, error)\n"); + } else if (BidiStreaming(method)) { + printer->Print(*vars, + "\t$Method$($Service$_$Method$Server) error\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print(*vars, + "\t$Method$(*$Request$, $Service$_$Method$Server) error\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print(*vars, + "\t$Method$($Service$_$Method$Server) error\n"); + } +} + +void PrintServerHandler(google::protobuf::io::Printer* printer, + const google::protobuf::MethodDescriptor* method, + map* vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type()->name(); + (*vars)["Response"] = method->output_type()->name(); + if (NoStreaming(method)) { + printer->Print(*vars, + "func _$Service$_$Method$_Handler(srv interface{}, ctx context.Context," + " buf []byte) (proto.Message, error) {\n"); + printer->Print(*vars, + "\tin := new($Request$)\n"); + printer->Print("\tif err := proto.Unmarshal(buf, in); err != nil {\n"); + printer->Print("\t\treturn nil, err\n"); + printer->Print("\t}\n"); + printer->Print(*vars, + "\tout, err := srv.($Service$Server).$Method$(ctx, in)\n"); + printer->Print("\tif err != nil {\n"); + printer->Print("\t\treturn nil, err\n"); + printer->Print("\t}\n"); + printer->Print("\treturn out, nil\n"); + printer->Print("}\n\n"); + } else if (BidiStreaming(method)) { + printer->Print(*vars, + "func _$Service$_$Method$_Handler(srv interface{}, stream rpc.Stream) " + "error {\n" + "\treturn srv.($Service$Server).$Method$(&$ServiceStruct$$Method$Server" + "{stream})\n" + "}\n\n"); + printer->Print(*vars, + "type $Service$_$Method$Server interface {\n" + "\tSend(*$Response$) error\n" + "\tRecv() (*$Request$, error)\n" + "\trpc.Stream\n" + "}\n\n"); + printer->Print(*vars, + "type $ServiceStruct$$Method$Server struct {\n" + "\trpc.Stream\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Server) Send(m *$Response$) error {\n" + "\treturn x.Stream.SendProto(m)\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Server) Recv() (*$Request$, error) " + "{\n" + "\tm := new($Request$)\n" + "\tif err := x.Stream.RecvProto(m); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\treturn m, nil\n" + "}\n\n"); + } else if (ServerOnlyStreaming(method)) { + printer->Print(*vars, + "func _$Service$_$Method$_Handler(srv interface{}, stream rpc.Stream) " + "error {\n" + "\tm := new($Request$)\n" + "\tif err := stream.RecvProto(m); err != nil {\n" + "\t\treturn err\n" + "\t}\n" + "\treturn srv.($Service$Server).$Method$(m, " + "&$ServiceStruct$$Method$Server{stream})\n" + "}\n\n"); + printer->Print(*vars, + "type $Service$_$Method$Server interface {\n" + "\tSend(*$Response$) error\n" + "\trpc.Stream\n" + "}\n\n"); + printer->Print(*vars, + "type $ServiceStruct$$Method$Server struct {\n" + "\trpc.Stream\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Server) Send(m *$Response$) error {\n" + "\treturn x.Stream.SendProto(m)\n" + "}\n\n"); + } else if (ClientOnlyStreaming(method)) { + printer->Print(*vars, + "func _$Service$_$Method$_Handler(srv interface{}, stream rpc.Stream) " + "error {\n" + "\treturn srv.($Service$Server).$Method$(&$ServiceStruct$$Method$Server" + "{stream})\n" + "}\n\n"); + printer->Print(*vars, + "type $Service$_$Method$Server interface {\n" + "\tSendAndClose(*$Response$) error\n" + "\tRecv() (*$Request$, error)\n" + "\trpc.Stream\n" + "}\n\n"); + printer->Print(*vars, + "type $ServiceStruct$$Method$Server struct {\n" + "\trpc.Stream\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Server) SendAndClose(m *$Response$) " + "error {\n" + "\tif err := x.Stream.SendProto(m); err != nil {\n" + "\t\treturn err\n" + "\t}\n" + "\treturn nil\n" + "}\n\n"); + printer->Print(*vars, + "func (x *$ServiceStruct$$Method$Server) Recv() (*$Request$, error) {\n" + "\tm := new($Request$)\n" + "\tif err := x.Stream.RecvProto(m); err != nil {\n" + "\t\treturn nil, err\n" + "\t}\n" + "\treturn m, nil\n" + "}\n\n"); + } +} + +void PrintServerMethodDesc(google::protobuf::io::Printer* printer, + const google::protobuf::MethodDescriptor* method, + map* vars) { + (*vars)["Method"] = method->name(); + printer->Print("\t\t{\n"); + printer->Print(*vars, + "\t\t\tMethodName:\t\"$Method$\",\n"); + printer->Print(*vars, + "\t\t\tHandler:\t_$Service$_$Method$_Handler,\n"); + printer->Print("\t\t},\n"); +} + +void PrintServerStreamingMethodDesc(google::protobuf::io::Printer* printer, + const google::protobuf::MethodDescriptor* method, + map* vars) { + (*vars)["Method"] = method->name(); + printer->Print("\t\t{\n"); + printer->Print(*vars, + "\t\t\tStreamName:\t\"$Method$\",\n"); + printer->Print(*vars, + "\t\t\tHandler:\t_$Service$_$Method$_Handler,\n"); + printer->Print("\t\t},\n"); +} + +void PrintServer(google::protobuf::io::Printer* printer, + const google::protobuf::ServiceDescriptor* service, + map* vars) { + (*vars)["Service"] = service->name(); + printer->Print(*vars, "type $Service$Server interface {\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintServerMethodDef(printer, service->method(i), vars); + } + printer->Print("}\n\n"); + + printer->Print(*vars, + "func RegisterService(s *rpc.Server, srv $Service$Server) {\n" + "\ts.RegisterService(&_$Service$_serviceDesc, srv)\n" + "}\n\n"); + + for (int i = 0; i < service->method_count(); ++i) { + PrintServerHandler(printer, service->method(i), vars); + } + + printer->Print(*vars, + "var _$Service$_serviceDesc = rpc.ServiceDesc{\n" + "\tServiceName: \"$Package$$Service$\",\n" + "\tHandlerType: (*$Service$Server)(nil),\n" + "\tMethods: []rpc.MethodDesc{\n"); + for (int i = 0; i < service->method_count(); ++i) { + if (NoStreaming(service->method(i))) { + PrintServerMethodDesc(printer, service->method(i), vars); + } + } + printer->Print("\t},\n"); + + printer->Print("\tStreams: []rpc.StreamDesc{\n"); + for (int i = 0; i < service->method_count(); ++i) { + if (!NoStreaming(service->method(i))) { + PrintServerStreamingMethodDesc(printer, service->method(i), vars); + } + } + printer->Print("\t},\n" + "}\n\n"); +} + +std::string BadToUnderscore(std::string str) { + for (unsigned i = 0; i < str.size(); ++i) { + if (!std::isalnum(str[i])) { + str[i] = '_'; + } + } + return str; +} + +string GetServices(const google::protobuf::FileDescriptor* file) { + string output; + google::protobuf::io::StringOutputStream output_stream(&output); + google::protobuf::io::Printer printer(&output_stream, '$'); + map vars; + + string package_name = !file->options().go_package().empty() + ? file->options().go_package() + : file->package(); + vars["PackageName"] = BadToUnderscore(package_name); + printer.Print(vars, "package $PackageName$\n\n"); + printer.Print("import (\n"); + if (HasClientOnlyStreaming(file)) { + printer.Print("\t\"fmt\"\n" + "\t\"io\"\n"); + } + printer.Print( + "\t\"google/net/grpc/go/rpc\"\n" + "\tcontext \"google/third_party/golang/go_net/context/context\"\n" + "\tproto \"google/net/proto2/go/proto\"\n" + ")\n\n"); + + // $Package$ is used to fully qualify method names. + vars["Package"] = file->package(); + if (!file->package().empty()) { + vars["Package"].append("."); + } + + for (int i = 0; i < file->service_count(); ++i) { + PrintClient(&printer, file->service(0), &vars); + printer.Print("\n"); + PrintServer(&printer, file->service(0), &vars); + printer.Print("\n"); + } + return output; +} + +} // namespace grpc_go_generator diff --git a/src/compiler/go_generator.h b/src/compiler/go_generator.h new file mode 100644 index 00000000000..fd5a05e5374 --- /dev/null +++ b/src/compiler/go_generator.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NET_GRPC_COMPILER_GO_GENERATOR_H_ +#define NET_GRPC_COMPILER_GO_GENERATOR_H_ + +#include + +namespace google { +namespace protobuf { +class FileDescriptor; +} // namespace protobuf +} // namespace google + +namespace grpc_go_generator { + +string GetServices(const google::protobuf::FileDescriptor* file); + +} // namespace grpc_go_generator + +#endif // NET_GRPC_COMPILER_GO_GENERATOR_H_ diff --git a/src/compiler/go_plugin.cc b/src/compiler/go_plugin.cc new file mode 100644 index 00000000000..f941840815e --- /dev/null +++ b/src/compiler/go_plugin.cc @@ -0,0 +1,83 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Generates go gRPC service interface out of Protobuf IDL. +// +// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto +// and net/proto2/compiler/public/plugin.h for more information on plugins. + +#include +#include + +using namespace std; + +#include "src/compiler/go_generator.h" +#include +#include +#include +#include +#include + +class GoGrpcGenerator : public google::protobuf::compiler::CodeGenerator { + public: + GoGrpcGenerator() {} + virtual ~GoGrpcGenerator() {} + + virtual bool Generate(const google::protobuf::FileDescriptor* file, + const string& parameter, + google::protobuf::compiler::GeneratorContext* context, + string* error) const { + // Get output file name. + string file_name; + if (file->name().size() > 6 && + file->name().find_last_of(".proto") == file->name().size() - 1) { + file_name = file->name().substr(0, file->name().size() - 6) + + "_grpc.pb.go"; + } else { + *error = "Invalid proto file name. Proto file must end with .proto"; + return false; + } + + std::unique_ptr output( + context->Open(file_name)); + google::protobuf::io::CodedOutputStream coded_out(output.get()); + string code = grpc_go_generator::GetServices(file); + coded_out.WriteRaw(code.data(), code.size()); + return true; + } +}; + +int main(int argc, char* argv[]) { + GoGrpcGenerator generator; + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +} From 00297df63b5c2d660dafa5314b3c87a57cfaf0b8 Mon Sep 17 00:00:00 2001 From: ctiller Date: Mon, 12 Jan 2015 11:23:09 -0800 Subject: [PATCH 25/29] Ensure flow control callbacks happen outside the transport lock. Split encoding into two phases: a collection phase to decide on what is allowed (by flow control) to be sent, and a framing phase when the data is actually sent. Perform the second phase outside of the transport mutex (but serially, guarded by t->writing) and make flow control callbacks during that phase. This will allow us to make further transport level calls in response to flow control callbacks, and will be needed by the forthcoming async api for C++. Change on 2015/01/12 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83774409 --- src/core/transport/chttp2/stream_encoder.c | 130 +++++---- src/core/transport/chttp2/stream_encoder.h | 15 +- src/core/transport/chttp2_transport.c | 246 ++++++++++-------- .../transport/chttp2/stream_encoder_test.c | 24 +- 4 files changed, 249 insertions(+), 166 deletions(-) diff --git a/src/core/transport/chttp2/stream_encoder.c b/src/core/transport/chttp2/stream_encoder.c index 8595a598793..92a36d0c160 100644 --- a/src/core/transport/chttp2/stream_encoder.c +++ b/src/core/transport/chttp2/stream_encoder.c @@ -68,8 +68,6 @@ typedef struct { gpr_uint8 last_was_header; /* output stream id */ gpr_uint32 stream_id; - /* number of flow controlled bytes written */ - gpr_uint32 output_size; gpr_slice_buffer *output; } framer_state; @@ -464,49 +462,31 @@ void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) { grpc_mdstr_unref(c->timeout_key_str); } -gpr_uint32 grpc_chttp2_encode_some(grpc_stream_op *ops, size_t *ops_count, - int eof, gpr_slice_buffer *output, - gpr_uint32 max_bytes, gpr_uint32 stream_id, - grpc_chttp2_hpack_compressor *compressor) { - framer_state st; +gpr_uint32 grpc_chttp2_preencode(grpc_stream_op *inops, size_t *inops_count, + gpr_uint32 max_flow_controlled_bytes, + grpc_stream_op_buffer *outops) { gpr_slice slice; grpc_stream_op *op; gpr_uint32 max_take_size; + gpr_uint32 flow_controlled_bytes_taken = 0; gpr_uint32 curop = 0; - gpr_uint32 nops = *ops_count; gpr_uint8 *p; - GPR_ASSERT(stream_id != 0); - - st.cur_frame_type = NONE; - st.last_was_header = 0; - st.stream_id = stream_id; - st.output = output; - st.output_size = 0; - - while (curop < nops) { - GPR_ASSERT(st.output_size <= max_bytes); - op = &ops[curop]; + while (curop < *inops_count) { + GPR_ASSERT(flow_controlled_bytes_taken <= max_flow_controlled_bytes); + op = &inops[curop]; switch (op->type) { case GRPC_NO_OP: + /* skip */ curop++; break; case GRPC_OP_FLOW_CTL_CB: - op->data.flow_ctl_cb.cb(op->data.flow_ctl_cb.arg, GRPC_OP_OK); - curop++; - break; - case GRPC_OP_METADATA: - hpack_enc(compressor, op->data.metadata, &st); - curop++; - break; case GRPC_OP_DEADLINE: - deadline_enc(compressor, op->data.deadline, &st); - curop++; - break; + case GRPC_OP_METADATA: case GRPC_OP_METADATA_BOUNDARY: - ensure_frame_type(&st, HEADER, 0); - finish_frame(&st, 1, 0); - st.last_was_header = 0; /* force a new header frame */ + /* these just get copied as they don't impact the number of flow + controlled bytes */ + grpc_sopb_append(outops, op, 1); curop++; break; case GRPC_OP_BEGIN_MESSAGE: @@ -525,42 +505,100 @@ gpr_uint32 grpc_chttp2_encode_some(grpc_stream_op *ops, size_t *ops_count, case GRPC_OP_SLICE: slice = op->data.slice; if (!GPR_SLICE_LENGTH(slice)) { + /* skip zero length slices */ + gpr_slice_unref(slice); curop++; break; } - if (st.output_size == max_bytes) { + max_take_size = max_flow_controlled_bytes - flow_controlled_bytes_taken; + if (max_take_size == 0) { goto exit_loop; } + if (GPR_SLICE_LENGTH(slice) > max_take_size) { + slice = gpr_slice_split_head(&op->data.slice, max_take_size); + grpc_sopb_add_slice(outops, slice); + } else { + /* consume this op immediately */ + grpc_sopb_append(outops, op, 1); + curop++; + } + flow_controlled_bytes_taken += GPR_SLICE_LENGTH(slice); + break; + } + } +exit_loop: + *inops_count -= curop; + memmove(inops, inops + curop, *inops_count * sizeof(grpc_stream_op)); + + return flow_controlled_bytes_taken; +} + +void grpc_chttp2_encode(grpc_stream_op *ops, size_t ops_count, int eof, + gpr_uint32 stream_id, + grpc_chttp2_hpack_compressor *compressor, + gpr_slice_buffer *output) { + framer_state st; + gpr_slice slice; + grpc_stream_op *op; + gpr_uint32 max_take_size; + gpr_uint32 curop = 0; + + GPR_ASSERT(stream_id != 0); + + st.cur_frame_type = NONE; + st.last_was_header = 0; + st.stream_id = stream_id; + st.output = output; + + while (curop < ops_count) { + op = &ops[curop]; + switch (op->type) { + case GRPC_NO_OP: + case GRPC_OP_BEGIN_MESSAGE: + gpr_log( + GPR_ERROR, + "These stream ops should be filtered out by grpc_chttp2_preencode"); + abort(); + case GRPC_OP_FLOW_CTL_CB: + op->data.flow_ctl_cb.cb(op->data.flow_ctl_cb.arg, GRPC_OP_OK); + curop++; + break; + case GRPC_OP_METADATA: + hpack_enc(compressor, op->data.metadata, &st); + curop++; + break; + case GRPC_OP_DEADLINE: + deadline_enc(compressor, op->data.deadline, &st); + curop++; + break; + case GRPC_OP_METADATA_BOUNDARY: + ensure_frame_type(&st, HEADER, 0); + finish_frame(&st, 1, 0); + st.last_was_header = 0; /* force a new header frame */ + curop++; + break; + case GRPC_OP_SLICE: + slice = op->data.slice; if (st.cur_frame_type == DATA && st.output->length - st.output_length_at_start_of_frame == GRPC_CHTTP2_MAX_PAYLOAD_LENGTH) { finish_frame(&st, 0, 0); } ensure_frame_type(&st, DATA, 1); - max_take_size = - GPR_MIN(max_bytes - st.output_size, - GRPC_CHTTP2_MAX_PAYLOAD_LENGTH + - st.output_length_at_start_of_frame - st.output->length); + max_take_size = GRPC_CHTTP2_MAX_PAYLOAD_LENGTH + + st.output_length_at_start_of_frame - st.output->length; if (GPR_SLICE_LENGTH(slice) > max_take_size) { slice = gpr_slice_split_head(&op->data.slice, max_take_size); } else { /* consume this op immediately */ curop++; } - st.output_size += GPR_SLICE_LENGTH(slice); gpr_slice_buffer_add(output, slice); break; } } -exit_loop: if (eof && st.cur_frame_type == NONE) { begin_frame(&st, DATA); } - finish_frame(&st, 1, eof && curop == nops); - - nops -= curop; - *ops_count = nops; - memmove(ops, ops + curop, nops * sizeof(grpc_stream_op)); - - return st.output_size; + finish_frame(&st, 1, eof); } diff --git a/src/core/transport/chttp2/stream_encoder.h b/src/core/transport/chttp2/stream_encoder.h index dad64697a52..4b093e84959 100644 --- a/src/core/transport/chttp2/stream_encoder.h +++ b/src/core/transport/chttp2/stream_encoder.h @@ -78,9 +78,16 @@ void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c, grpc_mdctx *mdctx); void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c); -gpr_uint32 grpc_chttp2_encode_some(grpc_stream_op *ops, size_t *ops_count, - int eof, gpr_slice_buffer *output, - gpr_uint32 max_bytes, gpr_uint32 stream_id, - grpc_chttp2_hpack_compressor *compressor); +/* select stream ops to be encoded, moving them from inops to outops, and + moving subsequent ops in inops forward in the queue */ +gpr_uint32 grpc_chttp2_preencode(grpc_stream_op *inops, size_t *inops_count, + gpr_uint32 max_flow_controlled_bytes, + grpc_stream_op_buffer *outops); + +/* encode stream ops to output */ +void grpc_chttp2_encode(grpc_stream_op *ops, size_t ops_count, int eof, + gpr_uint32 stream_id, + grpc_chttp2_hpack_compressor *compressor, + gpr_slice_buffer *output); #endif /* __GRPC_INTERNAL_TRANSPORT_CHTTP2_STREAM_ENCODER_H__ */ diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 5bf763e76f5..1b90d4715b3 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -71,6 +71,13 @@ typedef struct stream stream; typedef enum { /* streams that have pending writes */ WRITABLE = 0, + /* streams that have been selected to be written */ + WRITING, + /* streams that have just been written, and included a close */ + WRITTEN_CLOSED, + /* streams that have been cancelled and have some pending state updates + to perform */ + CANCELLED, /* streams that want to send window updates */ WINDOW_UPDATE, /* streams that are waiting to start because there are too many concurrent @@ -258,7 +265,12 @@ struct stream { gpr_uint32 outgoing_window; gpr_uint32 incoming_window; - gpr_uint8 write_closed; + /* when the application requests writes be closed, the write_closed is + 'queued'; when the close is flow controlled into the send path, we are + 'sending' it; when the write has been performed it is 'sent' */ + gpr_uint8 queued_write_closed; + gpr_uint8 sending_write_closed; + gpr_uint8 sent_write_closed; gpr_uint8 read_closed; gpr_uint8 cancelled; gpr_uint8 allow_window_updates; @@ -267,7 +279,10 @@ struct stream { stream_link links[STREAM_LIST_COUNT]; gpr_uint8 included[STREAM_LIST_COUNT]; + /* sops from application */ grpc_stream_op_buffer outgoing_sopb; + /* sops that have passed flow control to be written */ + grpc_stream_op_buffer writing_sopb; grpc_chttp2_data_parser parser; @@ -284,7 +299,7 @@ static int prepare_callbacks(transport *t); static void run_callbacks(transport *t); static int prepare_write(transport *t); -static void finish_write(void *t, grpc_endpoint_cb_status status); +static void perform_write(transport *t, grpc_endpoint *ep); static void lock(transport *t); static void unlock(transport *t); @@ -303,6 +318,7 @@ static void cancel_stream_id(transport *t, gpr_uint32 id, static void cancel_stream(transport *t, stream *s, grpc_status_code local_status, grpc_chttp2_error_code error_code, int send_rst); +static void finalize_cancellations(transport *t); static stream *lookup_stream(transport *t, gpr_uint32 id); static void remove_from_stream_map(transport *t, stream *s); static void maybe_start_some_streams(transport *t); @@ -518,7 +534,9 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs, t->settings[PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; s->incoming_window = t->settings[SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; - s->write_closed = 0; + s->queued_write_closed = 0; + s->sending_write_closed = 0; + s->sent_write_closed = 0; s->read_closed = 0; s->cancelled = 0; s->allow_window_updates = 0; @@ -526,8 +544,9 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs, memset(&s->links, 0, sizeof(s->links)); memset(&s->included, 0, sizeof(s->included)); grpc_sopb_init(&s->outgoing_sopb); - grpc_chttp2_data_parser_init(&s->parser); + grpc_sopb_init(&s->writing_sopb); grpc_sopb_init(&s->callback_sopb); + grpc_chttp2_data_parser_init(&s->parser); if (!server_data) { unlock(t); @@ -565,8 +584,9 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) { gpr_mu_unlock(&t->mu); grpc_sopb_destroy(&s->outgoing_sopb); - grpc_chttp2_data_parser_destroy(&s->parser); + grpc_sopb_destroy(&s->writing_sopb); grpc_sopb_destroy(&s->callback_sopb); + grpc_chttp2_data_parser_destroy(&s->parser); unref_transport(t); } @@ -575,6 +595,10 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) { * LIST MANAGEMENT */ +static int stream_list_empty(transport *t, stream_list_id id) { + return t->lists[id].head == NULL; +} + static stream *stream_list_remove_head(transport *t, stream_list_id id) { stream *s = t->lists[id].head; if (s) { @@ -666,6 +690,10 @@ static void unlock(transport *t) { } } + if (!t->writing) { + finalize_cancellations(t); + } + /* gather any callbacks that need to be made */ if (!t->calling_back && t->cb) { perform_callbacks = prepare_callbacks(t); @@ -709,53 +737,9 @@ static void unlock(transport *t) { } /* write some bytes if necessary */ - while (start_write) { - switch (grpc_endpoint_write(ep, t->outbuf.slices, t->outbuf.count, - finish_write, t)) { - case GRPC_ENDPOINT_WRITE_DONE: - /* grab the lock directly without wrappers since we just want to - continue writes if we loop: no need to check read callbacks again */ - gpr_mu_lock(&t->mu); - t->outbuf.count = 0; - t->outbuf.length = 0; - t->writing = start_write = prepare_write(t); - if (!start_write) { - if (!t->reading) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - gpr_cv_broadcast(&t->cv); - /* endpoint ref: safe because we'll still have the ref for write */ - unref_transport(t); - } - } - gpr_mu_unlock(&t->mu); - if (!start_write) { - unref_transport(t); - } - break; - case GRPC_ENDPOINT_WRITE_ERROR: - start_write = 0; - /* use the wrapper lock/unlock here as we drop_connection, causing - read callbacks to be queued (which will be cleared during unlock) */ - lock(t); - t->outbuf.count = 0; - t->outbuf.length = 0; - t->writing = 0; - drop_connection(t); - if (!t->reading) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - gpr_cv_broadcast(&t->cv); - /* endpoint ref: safe because we'll still have the ref for write */ - unref_transport(t); - } - unlock(t); - unref_transport(t); - break; - case GRPC_ENDPOINT_WRITE_PENDING: - start_write = 0; - break; - } + if (start_write) { + /* ultimately calls unref_transport(t); and clears t->writing */ + perform_write(t, ep); } if (perform_callbacks || call_closed || num_goaways) { @@ -788,32 +772,10 @@ static void push_setting(transport *t, grpc_chttp2_setting_id id, } } -static void finish_write(void *tp, grpc_endpoint_cb_status error) { - transport *t = tp; - - lock(t); - if (error != GRPC_ENDPOINT_CB_OK) { - drop_connection(t); - } - t->outbuf.count = 0; - t->outbuf.length = 0; - /* leave the writing flag up on shutdown to prevent further writes in unlock() - from starting */ - t->writing = 0; - if (!t->reading) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - gpr_cv_broadcast(&t->cv); - unref_transport(t); /* safe because we'll still have the ref for write */ - } - unlock(t); - - unref_transport(t); -} - static int prepare_write(transport *t) { stream *s; gpr_slice_buffer tempbuf; + gpr_uint32 window_delta; /* simple writes are queued to qbuf, and flushed here */ tempbuf = t->qbuf; @@ -834,17 +796,16 @@ static int prepare_write(transport *t) { /* for each stream that's become writable, frame it's data (according to available window sizes) and add to the output buffer */ while (t->outgoing_window && (s = stream_list_remove_head(t, WRITABLE))) { - gpr_uint32 written = grpc_chttp2_encode_some( - s->outgoing_sopb.ops, &s->outgoing_sopb.nops, s->write_closed, - &t->outbuf, GPR_MIN(t->outgoing_window, s->outgoing_window), s->id, - &t->hpack_compressor); - t->outgoing_window -= written; - s->outgoing_window -= written; - - /* if there are no more writes to do and writes are closed, we need to - queue a callback to let the application know */ - if (s->write_closed && s->outgoing_sopb.nops == 0) { - stream_list_join(t, s, PENDING_CALLBACKS); + window_delta = grpc_chttp2_preencode( + s->outgoing_sopb.ops, &s->outgoing_sopb.nops, + GPR_MIN(t->outgoing_window, s->outgoing_window), &s->writing_sopb); + t->outgoing_window -= window_delta; + s->outgoing_window -= window_delta; + + s->sending_write_closed = + s->queued_write_closed && s->outgoing_sopb.nops == 0; + if (s->writing_sopb.nops > 0 || s->sending_write_closed) { + stream_list_join(t, s, WRITING); } /* if there are still writes to do and the stream still has window @@ -857,25 +818,89 @@ static int prepare_write(transport *t) { /* for each stream that wants to update its window, add that window here */ while ((s = stream_list_remove_head(t, WINDOW_UPDATE))) { - gpr_uint32 window_add = + window_delta = t->settings[LOCAL_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] - s->incoming_window; - if (!s->read_closed && window_add) { - gpr_slice_buffer_add(&t->outbuf, - grpc_chttp2_window_update_create(s->id, window_add)); - s->incoming_window += window_add; + if (!s->read_closed && window_delta) { + gpr_slice_buffer_add( + &t->outbuf, grpc_chttp2_window_update_create(s->id, window_delta)); + s->incoming_window += window_delta; } } /* if the transport is ready to send a window update, do so here also */ if (t->incoming_window < t->connection_window_target * 3 / 4) { - gpr_uint32 window_add = t->connection_window_target - t->incoming_window; + window_delta = t->connection_window_target - t->incoming_window; gpr_slice_buffer_add(&t->outbuf, - grpc_chttp2_window_update_create(0, window_add)); - t->incoming_window += window_add; + grpc_chttp2_window_update_create(0, window_delta)); + t->incoming_window += window_delta; } - return t->outbuf.length > 0; + return t->outbuf.length > 0 || !stream_list_empty(t, WRITING); +} + +static void finalize_outbuf(transport *t) { + stream *s; + + while ((s = stream_list_remove_head(t, WRITING))) { + grpc_chttp2_encode(s->writing_sopb.ops, s->writing_sopb.nops, + s->sending_write_closed, s->id, &t->hpack_compressor, + &t->outbuf); + s->writing_sopb.nops = 0; + if (s->sending_write_closed) { + stream_list_join(t, s, WRITTEN_CLOSED); + } + } +} + +static void finish_write_common(transport *t, int success) { + stream *s; + + lock(t); + if (!success) { + drop_connection(t); + } + while ((s = stream_list_remove_head(t, WRITTEN_CLOSED))) { + s->sent_write_closed = 1; + stream_list_join(t, s, PENDING_CALLBACKS); + } + t->outbuf.count = 0; + t->outbuf.length = 0; + /* leave the writing flag up on shutdown to prevent further writes in unlock() + from starting */ + t->writing = 0; + if (!t->reading) { + grpc_endpoint_destroy(t->ep); + t->ep = NULL; + gpr_cv_broadcast(&t->cv); + unref_transport(t); /* safe because we'll still have the ref for write */ + } + unlock(t); + + unref_transport(t); +} + +static void finish_write(void *tp, grpc_endpoint_cb_status error) { + transport *t = tp; + finish_write_common(t, error == GRPC_ENDPOINT_CB_OK); +} + +static void perform_write(transport *t, grpc_endpoint *ep) { + finalize_outbuf(t); + + GPR_ASSERT(t->outbuf.count > 0); + + switch (grpc_endpoint_write(ep, t->outbuf.slices, t->outbuf.count, + finish_write, t)) { + case GRPC_ENDPOINT_WRITE_DONE: + finish_write_common(t, 1); + break; + case GRPC_ENDPOINT_WRITE_ERROR: + finish_write_common(t, 0); + break; + case GRPC_ENDPOINT_WRITE_PENDING: + break; + } } static void maybe_start_some_streams(transport *t) { @@ -901,19 +926,14 @@ static void send_batch(grpc_transport *gt, grpc_stream *gs, grpc_stream_op *ops, lock(t); if (is_last) { - s->write_closed = 1; + s->queued_write_closed = 1; } if (!s->cancelled) { grpc_sopb_append(&s->outgoing_sopb, ops, ops_count); - if (is_last && s->outgoing_sopb.nops == 0) { - if (s->id != 0) { - gpr_slice_buffer_add(&t->qbuf, - grpc_chttp2_data_frame_create_empty_close(s->id)); - } - } else if (s->id == 0) { + if (s->id == 0) { stream_list_join(t, s, WAITING_FOR_CONCURRENCY); maybe_start_some_streams(t); - } else if (s->outgoing_window) { + } else { stream_list_join(t, s, WRITABLE); } } else { @@ -967,12 +987,22 @@ static void send_ping(grpc_transport *gt, void (*cb)(void *user_data), * INPUT PROCESSING */ +static void finalize_cancellations(transport *t) { + stream *s; + + while ((s = stream_list_remove_head(t, CANCELLED))) { + s->read_closed = 1; + s->sent_write_closed = 1; + stream_list_join(t, s, PENDING_CALLBACKS); + } +} + static void cancel_stream_inner(transport *t, stream *s, gpr_uint32 id, grpc_status_code local_status, grpc_chttp2_error_code error_code, int send_rst) { - char buffer[32]; int had_outgoing; + char buffer[32]; if (s) { /* clear out any unreported input & output: nobody cares anymore */ @@ -981,10 +1011,9 @@ static void cancel_stream_inner(transport *t, stream *s, gpr_uint32 id, grpc_sopb_reset(&s->outgoing_sopb); if (s->cancelled) { send_rst = 0; - } else if (!s->read_closed || !s->write_closed || had_outgoing) { + } else if (!s->read_closed || !s->sent_write_closed || had_outgoing) { s->cancelled = 1; - s->read_closed = 1; - s->write_closed = 1; + stream_list_join(t, s, CANCELLED); sprintf(buffer, "%d", local_status); grpc_sopb_add_metadata( @@ -1667,8 +1696,7 @@ static int prepare_callbacks(transport *t) { s->parser.incoming_sopb = s->callback_sopb; s->callback_sopb = temp_sopb; - s->callback_state = compute_state( - s->write_closed && s->outgoing_sopb.nops == 0, s->read_closed); + s->callback_state = compute_state(s->sent_write_closed, s->read_closed); if (s->callback_state == GRPC_STREAM_CLOSED) { remove_from_stream_map(t, s); if (s->published_close) { diff --git a/test/core/transport/chttp2/stream_encoder_test.c b/test/core/transport/chttp2/stream_encoder_test.c index 3ee11d94e85..ba552786db0 100644 --- a/test/core/transport/chttp2/stream_encoder_test.c +++ b/test/core/transport/chttp2/stream_encoder_test.c @@ -64,15 +64,20 @@ static gpr_slice create_test_slice(size_t length) { static void verify_sopb(size_t window_available, int eof, size_t expect_window_used, const char *expected) { gpr_slice_buffer output; + grpc_stream_op_buffer encops; gpr_slice merged; gpr_slice expect = parse_hexstring(expected); gpr_slice_buffer_init(&output); + grpc_sopb_init(&encops); GPR_ASSERT(expect_window_used == - grpc_chttp2_encode_some(g_sopb.ops, &g_sopb.nops, eof, &output, - window_available, 0xdeadbeef, - &g_compressor)); + grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, window_available, + &encops)); + grpc_chttp2_encode(encops.ops, encops.nops, eof, 0xdeadbeef, &g_compressor, + &output); + encops.nops = 0; merged = grpc_slice_merge(output.slices, output.count); gpr_slice_buffer_destroy(&output); + grpc_sopb_destroy(&encops); if (0 != gpr_slice_cmp(merged, expect)) { char *expect_str = @@ -240,21 +245,25 @@ static void test_decode_random_headers_inner(int max_len) { test_decode_random_header_state st; gpr_slice_buffer output; gpr_slice merged; + grpc_stream_op_buffer encops; grpc_chttp2_hpack_parser parser; grpc_chttp2_hpack_parser_init(&parser, g_mdctx); + grpc_sopb_init(&encops); gpr_log(GPR_INFO, "max_len = %d", max_len); - for (i = 0; i < 100000; i++) { + for (i = 0; i < 10000; i++) { randstr(st.key, max_len); randstr(st.value, max_len); add_sopb_header(st.key, st.value); gpr_slice_buffer_init(&output); - GPR_ASSERT(0 == grpc_chttp2_encode_some(g_sopb.ops, &g_sopb.nops, 0, - &output, 0, 0xdeadbeef, - &g_compressor)); + GPR_ASSERT(0 == + grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, 0, &encops)); + grpc_chttp2_encode(encops.ops, encops.nops, 0, 0xdeadbeef, &g_compressor, + &output); + encops.nops = 0; merged = grpc_slice_merge(output.slices, output.count); gpr_slice_buffer_destroy(&output); @@ -269,6 +278,7 @@ static void test_decode_random_headers_inner(int max_len) { } grpc_chttp2_hpack_parser_destroy(&parser); + grpc_sopb_destroy(&encops); } #define DECL_TEST_DECODE_RANDOM_HEADERS(n) \ From 0617057a39b726a91c610813b85138b85c3c5a85 Mon Sep 17 00:00:00 2001 From: yangg Date: Mon, 12 Jan 2015 13:12:45 -0800 Subject: [PATCH 26/29] Make interop server buildable on opensource build. Change on 2015/01/12 by yangg ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83783816 --- test/cpp/interop/server.cc | 231 +++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 test/cpp/interop/server.cc diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc new file mode 100644 index 00000000000..561b134c279 --- /dev/null +++ b/test/cpp/interop/server.cc @@ -0,0 +1,231 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include +#include +#include +#include "test/core/end2end/data/ssl_test_data.h" +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp/interop/test.pb.h" +#include "test/cpp/interop/empty.pb.h" +#include "test/cpp/interop/messages.pb.h" + +DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); +DEFINE_int32(port, 0, "Server port."); + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerCredentials; +using grpc::ServerCredentialsFactory; +using grpc::ServerReader; +using grpc::ServerReaderWriter; +using grpc::ServerWriter; +using grpc::SslServerCredentialsOptions; +using grpc::testing::Payload; +using grpc::testing::PayloadType; +using grpc::testing::SimpleRequest; +using grpc::testing::SimpleResponse; +using grpc::testing::StreamingInputCallRequest; +using grpc::testing::StreamingInputCallResponse; +using grpc::testing::StreamingOutputCallRequest; +using grpc::testing::StreamingOutputCallResponse; +using grpc::testing::TestService; +using grpc::Status; + +bool SetPayload(PayloadType type, int size, Payload* payload) { + PayloadType response_type = type; + // TODO(yangg): Support UNCOMPRESSABLE payload. + if (type != PayloadType::COMPRESSABLE) { + return false; + } + payload->set_type(response_type); + std::unique_ptr body(new char[size]()); + payload->set_body(body.get(), size); + return true; +} + +class TestServiceImpl : public TestService::Service { + public: + Status EmptyCall(ServerContext* context, const grpc::testing::Empty* request, + grpc::testing::Empty* response) { + return Status::OK; + } + + Status UnaryCall(ServerContext* context, const SimpleRequest* request, + SimpleResponse* response) { + if (request->has_response_size() && request->response_size() > 0) { + if (!SetPayload(request->response_type(), request->response_size(), + response->mutable_payload())) { + return Status(grpc::StatusCode::INTERNAL, "Error creating payload."); + } + } + return Status::OK; + } + + Status StreamingOutputCall( + ServerContext* context, const StreamingOutputCallRequest* request, + ServerWriter* writer) { + StreamingOutputCallResponse response; + bool write_success = true; + response.mutable_payload()->set_type(request->response_type()); + for (int i = 0; write_success && i < request->response_parameters_size(); + i++) { + response.mutable_payload()->set_body( + grpc::string(request->response_parameters(i).size(), '\0')); + write_success = writer->Write(response); + } + if (write_success) { + return Status::OK; + } else { + return Status(grpc::StatusCode::INTERNAL, "Error writing response."); + } + } + + Status StreamingInputCall(ServerContext* context, + ServerReader* reader, + StreamingInputCallResponse* response) { + StreamingInputCallRequest request; + int aggregated_payload_size = 0; + while (reader->Read(&request)) { + if (request.has_payload() && request.payload().has_body()) { + aggregated_payload_size += request.payload().body().size(); + } + } + response->set_aggregated_payload_size(aggregated_payload_size); + return Status::OK; + } + + Status FullDuplexCall( + ServerContext* context, + ServerReaderWriter* stream) { + StreamingOutputCallRequest request; + StreamingOutputCallResponse response; + bool write_success = true; + while (write_success && stream->Read(&request)) { + response.mutable_payload()->set_type(request.payload().type()); + if (request.response_parameters_size() == 0) { + return Status(grpc::StatusCode::INTERNAL, + "Request does not have response parameters."); + } + response.mutable_payload()->set_body( + grpc::string(request.response_parameters(0).size(), '\0')); + write_success = stream->Write(response); + } + if (write_success) { + return Status::OK; + } else { + return Status(grpc::StatusCode::INTERNAL, "Error writing response."); + } + } + + Status HalfDuplexCall( + ServerContext* context, + ServerReaderWriter* stream) { + std::vector requests; + StreamingOutputCallRequest request; + while (stream->Read(&request)) { + requests.push_back(request); + } + + StreamingOutputCallResponse response; + bool write_success = true; + for (unsigned int i = 0; write_success && i < requests.size(); i++) { + response.mutable_payload()->set_type(requests[i].payload().type()); + if (requests[i].response_parameters_size() == 0) { + return Status(grpc::StatusCode::INTERNAL, + "Request does not have response parameters."); + } + response.mutable_payload()->set_body( + grpc::string(requests[i].response_parameters(0).size(), '\0')); + write_success = stream->Write(response); + } + if (write_success) { + return Status::OK; + } else { + return Status(grpc::StatusCode::INTERNAL, "Error writing response."); + } + } +}; + +void RunServer() { + std::ostringstream server_address; + server_address << "localhost:" << FLAGS_port; + TestServiceImpl service; + + SimpleRequest request; + SimpleResponse response; + + ServerBuilder builder; + builder.AddPort(server_address.str()); + builder.RegisterService(service.service()); + if (FLAGS_enable_ssl) { + SslServerCredentialsOptions ssl_opts = { + "", + {reinterpret_cast(test_server1_key), + test_server1_key_size}, + {reinterpret_cast(test_server1_cert), + test_server1_cert_size}}; + std::shared_ptr creds = + ServerCredentialsFactory::SslCredentials(ssl_opts); + builder.SetCredentials(creds); + } + std::unique_ptr server(builder.BuildAndStart()); + gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str()); + while (true) { + std::this_thread::sleep_for(std::chrono::seconds(5)); + } +} + +int main(int argc, char** argv) { + grpc_init(); + google::ParseCommandLineFlags(&argc, &argv, true); + + GPR_ASSERT(FLAGS_port != 0); + RunServer(); + + grpc_shutdown(); + return 0; +} From d74729d8c78ab50d0219f03e831f1aabcbad0b15 Mon Sep 17 00:00:00 2001 From: ctiller Date: Mon, 12 Jan 2015 13:31:36 -0800 Subject: [PATCH 27/29] Pre-allocate, check, and consume method, scheme, and content-type headers at the server. Verify that method, scheme, and te trailers are present, and error out if not. Complain if content-type doesn't match the format, but don't error out. This currently, for now, blindly allows all three schemes (grpc, http, https) without verification, although that will change once the C implementation finishes switching to http/https. Cloned from CL 82558661 by 'g4 patch'. Original change by klempner@klempner:grpc_metadata:808:citc on 2014/12/19 18:41:47. Change on 2015/01/12 by ctiller ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83785251 --- src/core/channel/http_server_filter.c | 108 ++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 14 deletions(-) diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 9a20d79c61f..44eab43f09d 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -32,13 +32,26 @@ */ #include "src/core/channel/http_server_filter.h" + +#include #include -typedef struct call_data { int sent_status; } call_data; +typedef struct call_data { + int sent_status; + int seen_scheme; + int seen_method; + int seen_te_trailers; +} call_data; typedef struct channel_data { grpc_mdelem *te_trailers; - grpc_mdelem *status_md; + grpc_mdelem *method; + grpc_mdelem *http_scheme; + grpc_mdelem *https_scheme; + /* TODO(klempner): Remove this once we stop using it */ + grpc_mdelem *grpc_scheme; + grpc_mdelem *content_type; + grpc_mdelem *status; } channel_data; /* used to silence 'variable not used' warnings */ @@ -56,20 +69,54 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, channel_data *channeld = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); - ignore_unused(calld); - ignore_unused(channeld); - switch (op->type) { case GRPC_RECV_METADATA: - /* check if it's a te: trailers header */ - if (op->data.metadata == channeld->te_trailers) { + /* Check if it is one of the headers we care about. */ + if (op->data.metadata == channeld->te_trailers || + op->data.metadata == channeld->method || + op->data.metadata == channeld->http_scheme || + op->data.metadata == channeld->https_scheme || + op->data.metadata == channeld->grpc_scheme || + op->data.metadata == channeld->content_type) { /* swallow it */ + if (op->data.metadata == channeld->method) { + calld->seen_method = 1; + } else if (op->data.metadata->key == channeld->http_scheme->key) { + calld->seen_scheme = 1; + } else if (op->data.metadata == channeld->te_trailers) { + calld->seen_te_trailers = 1; + } + /* TODO(klempner): Track that we've seen all the headers we should + require */ grpc_mdelem_unref(op->data.metadata); op->done_cb(op->user_data, GRPC_OP_OK); - } else if (op->data.metadata->key == channeld->te_trailers->key) { - gpr_log(GPR_ERROR, "Invalid te: header: '%s'", + } else if (op->data.metadata->key == channeld->content_type->key) { + if (strncmp(grpc_mdstr_as_c_string(op->data.metadata->value), + "application/grpc+", 17) == 0) { + /* Although the C implementation doesn't (currently) generate them, + any + custom +-suffix is explicitly valid. */ + /* TODO(klempner): We should consider preallocating common values such + as +proto or +json, or at least stashing them if we see them. */ + /* TODO(klempner): Should we be surfacing this to application code? */ + } else { + /* TODO(klempner): We're currently allowing this, but we shouldn't + see it without a proxy so log for now. */ + gpr_log(GPR_INFO, "Unexpected content-type %s", + channeld->content_type->key); + } + grpc_mdelem_unref(op->data.metadata); + op->done_cb(op->user_data, GRPC_OP_OK); + } else if (op->data.metadata->key == channeld->te_trailers->key || + op->data.metadata->key == channeld->method->key || + op->data.metadata->key == channeld->http_scheme->key || + op->data.metadata->key == channeld->content_type->key) { + gpr_log(GPR_ERROR, "Invalid %s: header: '%s'", + grpc_mdstr_as_c_string(op->data.metadata->key), grpc_mdstr_as_c_string(op->data.metadata->value)); - /* swallow it */ + /* swallow it and error everything out. */ + /* TODO(klempner): We ought to generate more descriptive error messages + on the wire here. */ grpc_mdelem_unref(op->data.metadata); op->done_cb(op->user_data, GRPC_OP_OK); grpc_call_element_send_cancel(elem); @@ -78,14 +125,33 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_next_op(elem, op); } break; + case GRPC_RECV_END_OF_INITIAL_METADATA: + /* Have we seen the required http2 transport headers? + (:method, :scheme, content-type, with :path and :authority covered + at the channel level right now) */ + if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers) { + grpc_call_next_op(elem, op); + } else { + if (!calld->seen_method) { + gpr_log(GPR_ERROR, "Missing :method header"); + } else if (!calld->seen_scheme) { + gpr_log(GPR_ERROR, "Missing :scheme header"); + } else if (!calld->seen_te_trailers) { + gpr_log(GPR_ERROR, "Missing te trailers header"); + } + /* Error this call out */ + op->done_cb(op->user_data, GRPC_OP_OK); + grpc_call_element_send_cancel(elem); + } + break; case GRPC_SEND_START: case GRPC_SEND_METADATA: /* If we haven't sent status 200 yet, we need to so so because it needs to come before any non : prefixed metadata. */ if (!calld->sent_status) { calld->sent_status = 1; - /* status_md is reffed by grpc_call_element_send_metadata */ - grpc_call_element_send_metadata(elem, channeld->status_md); + /* status is reffed by grpc_call_element_send_metadata */ + grpc_call_element_send_metadata(elem, channeld->status); } grpc_call_next_op(elem, op); break; @@ -124,6 +190,9 @@ static void init_call_elem(grpc_call_element *elem, /* initialize members */ calld->sent_status = 0; + calld->seen_scheme = 0; + calld->seen_method = 0; + calld->seen_te_trailers = 0; } /* Destructor for call_data */ @@ -151,7 +220,13 @@ static void init_channel_elem(grpc_channel_element *elem, /* initialize members */ channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers"); - channeld->status_md = grpc_mdelem_from_strings(mdctx, ":status", "200"); + channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200"); + channeld->method = grpc_mdelem_from_strings(mdctx, ":method", "POST"); + channeld->http_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "http"); + channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https"); + channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc"); + channeld->content_type = + grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc"); } /* Destructor for channel data */ @@ -160,7 +235,12 @@ static void destroy_channel_elem(grpc_channel_element *elem) { channel_data *channeld = elem->channel_data; grpc_mdelem_unref(channeld->te_trailers); - grpc_mdelem_unref(channeld->status_md); + grpc_mdelem_unref(channeld->status); + grpc_mdelem_unref(channeld->method); + grpc_mdelem_unref(channeld->http_scheme); + grpc_mdelem_unref(channeld->https_scheme); + grpc_mdelem_unref(channeld->grpc_scheme); + grpc_mdelem_unref(channeld->content_type); } const grpc_channel_filter grpc_http_server_filter = { From 99e317a8f8c9f71ede5fc2587589aa60989d3dac Mon Sep 17 00:00:00 2001 From: hongyu Date: Mon, 12 Jan 2015 13:49:25 -0800 Subject: [PATCH 28/29] grpc census hash_table test coverage improvements. Change on 2015/01/12 by hongyu ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83786701 --- src/core/statistics/hash_table.c | 6 +++--- test/core/statistics/hash_table_test.c | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/statistics/hash_table.c b/src/core/statistics/hash_table.c index f0105ee6830..1aee86d3a45 100644 --- a/src/core/statistics/hash_table.c +++ b/src/core/statistics/hash_table.c @@ -141,10 +141,10 @@ static gpr_int32 find_bucket_idx(const census_ht* ht, census_ht_key key) { static int keys_match(const census_ht_option* opt, const ht_entry* p, const census_ht_key key) { + GPR_ASSERT(opt->key_type == CENSUS_HT_UINT64 || + opt->key_type == CENSUS_HT_POINTER); if (opt->key_type == CENSUS_HT_UINT64) return p->key.val == key.val; - if (opt->key_type == CENSUS_HT_POINTER) - return !opt->compare_keys((p->key).ptr, key.ptr); - return 0; + return !opt->compare_keys((p->key).ptr, key.ptr); } static entry_locator ht_find(const census_ht* ht, census_ht_key key) { diff --git a/test/core/statistics/hash_table_test.c b/test/core/statistics/hash_table_test.c index fb75de520e8..8c768241935 100644 --- a/test/core/statistics/hash_table_test.c +++ b/test/core/statistics/hash_table_test.c @@ -123,7 +123,8 @@ static void test_value_and_key_deleter() { &free_data, &free_data}; census_ht* ht = census_ht_create(&opt); census_ht_key key; - char* val; + char* val = NULL; + char* val2 = NULL; key.ptr = gpr_malloc(100); val = gpr_malloc(10); strcpy(val, "value"); @@ -132,6 +133,17 @@ static void test_value_and_key_deleter() { GPR_ASSERT(census_ht_get_size(ht) == 0); census_ht_insert(ht, key, val); GPR_ASSERT(census_ht_get_size(ht) == 1); + val = census_ht_find(ht, key); + GPR_ASSERT(val != NULL); + GPR_ASSERT(strcmp(val, "value") == 0); + /* Insert same key different value, old value is overwritten. */ + val2 = gpr_malloc(10); + strcpy(val2, "v2"); + census_ht_insert(ht, key, val2); + GPR_ASSERT(census_ht_get_size(ht) == 1); + val2 = census_ht_find(ht, key); + GPR_ASSERT(val2 != NULL); + GPR_ASSERT(strcmp(val2, "v2") == 0); census_ht_destroy(ht); } From 35e7b0cb5ce5ea6721353eb8d698a1131c1096ef Mon Sep 17 00:00:00 2001 From: rsilvera Date: Mon, 12 Jan 2015 13:52:04 -0800 Subject: [PATCH 29/29] Fix gRPC compilation failure Update location of rpc_method.cc on the Makefile Change on 2015/01/12 by rsilvera ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83786942 --- Makefile | 2 +- build.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 201a10c410f..2183beb0bf7 100644 --- a/Makefile +++ b/Makefile @@ -1574,7 +1574,7 @@ LIBGRPC++_SRC = \ src/cpp/client/credentials.cc \ src/cpp/client/internal_stub.cc \ src/cpp/proto/proto_utils.cc \ - src/cpp/rpc_method.cc \ + src/cpp/common/rpc_method.cc \ src/cpp/server/async_server.cc \ src/cpp/server/async_server_context.cc \ src/cpp/server/completion_queue.cc \ diff --git a/build.json b/build.json index 968c1dfadec..219ff23fe13 100644 --- a/build.json +++ b/build.json @@ -335,7 +335,7 @@ "src/cpp/client/credentials.cc", "src/cpp/client/internal_stub.cc", "src/cpp/proto/proto_utils.cc", - "src/cpp/rpc_method.cc", + "src/cpp/common/rpc_method.cc", "src/cpp/server/async_server.cc", "src/cpp/server/async_server_context.cc", "src/cpp/server/completion_queue.cc",