diff options
Diffstat (limited to 'src')
259 files changed, 5390 insertions, 14596 deletions
diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index 3ccfd5b037..be64776402 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -39,6 +39,11 @@ #include "src/compiler/objective_c_generator.h" #include "src/compiler/objective_c_generator_helpers.h" +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> + +using ::google::protobuf::compiler::objectivec::ProtobufLibraryFrameworkName; +using ::google::protobuf::compiler::objectivec::IsProtobufLibraryBundledProtoFile; + class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: ObjectiveCGrpcGenerator() {} @@ -72,7 +77,21 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { for (int i = 0; i < file->dependency_count(); i++) { ::grpc::string header = grpc_objective_c_generator::MessageHeaderName( file->dependency(i)); - proto_imports += ::grpc::string("#import \"") + header + "\"\n"; + const grpc::protobuf::FileDescriptor *dependency = file->dependency(i); + if (IsProtobufLibraryBundledProtoFile(dependency)) { + ::grpc::string base_name = header; + grpc_generator::StripPrefix(&base_name, "google/protobuf/"); + // create the import code snippet + proto_imports += + "#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n" + " #import <" + ::grpc::string(ProtobufLibraryFrameworkName) + + "/" + base_name + ">\n" + "#else\n" + " #import \"" + header + "\"\n" + "#endif\n"; + } else { + proto_imports += ::grpc::string("#import \"") + header + "\"\n"; + } } ::grpc::string declarations; @@ -85,7 +104,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { static const ::grpc::string kNonNullEnd = "\nNS_ASSUME_NONNULL_END\n"; Write(context, file_name + ".pbrpc.h", - imports + '\n' + proto_imports + '\n' + kNonNullBegin + + imports + '\n' + proto_imports + '\n' + kNonNullBegin + declarations + kNonNullEnd); } diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 721ba82d8f..9acacbd92d 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -91,11 +91,13 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, connector *c = arg; grpc_closure *notify; gpr_mu_lock(&c->mu); + grpc_error *error = GRPC_ERROR_NONE; if (c->connecting_endpoint == NULL) { memset(c->result, 0, sizeof(*c->result)); gpr_mu_unlock(&c->mu); } else if (status != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status); + error = grpc_error_set_int(GRPC_ERROR_CREATE("Secure handshake failed"), + GRPC_ERROR_INT_SECURITY_STATUS, status); memset(c->result, 0, sizeof(*c->result)); c->connecting_endpoint = NULL; gpr_mu_unlock(&c->mu); @@ -113,7 +115,7 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, } notify = c->notify; c->notify = NULL; - grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_NONE, NULL); + grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); } static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, diff --git a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c index bd87253ed3..7d5279b9da 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c @@ -36,11 +36,14 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/transport/metadata.h" +extern int grpc_http_write_state_trace; + void grpc_chttp2_plugin_init(void) { grpc_chttp2_base64_encode_and_huffman_compress = grpc_chttp2_base64_encode_and_huffman_compress_impl; grpc_register_tracer("http", &grpc_http_trace); grpc_register_tracer("flowctl", &grpc_flowctl_trace); + grpc_register_tracer("http_write_state", &grpc_http_write_state_trace); } void grpc_chttp2_plugin_shutdown(void) {} diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 38e782b9b4..d050467a02 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -48,6 +48,7 @@ #include "src/core/ext/transport/chttp2/transport/status_conversion.h" #include "src/core/ext/transport/chttp2/transport/timeout_encoding.h" #include "src/core/lib/http/parser.h" +#include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/static_metadata.h" @@ -60,9 +61,9 @@ #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024) #define MAX_CLIENT_STREAM_ID 0x7fffffffu - int grpc_http_trace = 0; int grpc_flowctl_trace = 0; +int grpc_http_write_state_trace = 0; #define TRANSPORT_FROM_WRITING(tw) \ ((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \ @@ -88,10 +89,16 @@ static const grpc_transport_vtable vtable; static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); +static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t, + grpc_error *error); + +static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); +static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, grpc_error *error); /** Set a transport level setting, and push it to our peer */ -static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, - uint32_t value); +static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, + grpc_chttp2_setting_id id, uint32_t value); /** Start disconnection chain */ static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -137,7 +144,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global); static void incoming_byte_stream_update_flow_control( - grpc_chttp2_transport_global *transport_global, + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, size_t max_size_hint, size_t have_already); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, @@ -201,6 +208,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, gpr_free(t); } +/*#define REFCOUNTING_DEBUG 1*/ #ifdef REFCOUNTING_DEBUG #define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__) #define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t, r, __FILE__, __LINE__) @@ -231,7 +239,7 @@ static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); } static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, const grpc_channel_args *channel_args, - grpc_endpoint *ep, uint8_t is_client) { + grpc_endpoint *ep, bool is_client) { size_t i; int j; @@ -273,6 +281,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_closure_init(&t->writing_action, writing_action, t); grpc_closure_init(&t->reading_action, reading_action, t); grpc_closure_init(&t->parsing_action, parsing_action, t); + grpc_closure_init(&t->initiate_writing, initiate_writing, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); @@ -286,6 +295,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, gpr_slice_buffer_add( &t->global.qbuf, gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); + grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write"); } /* 8 is a random stab in the dark as to a good initial size: it's small enough that it shouldn't waste memory for infrequently used connections, yet @@ -311,11 +321,12 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, /* configure http2 the way we like it */ if (is_client) { - push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); - push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); } - push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW); - push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, + DEFAULT_WINDOW); + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, DEFAULT_MAX_HEADER_LIST_SIZE); if (channel_args) { @@ -329,7 +340,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_MAX_CONCURRENT_STREAMS); } else { - push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, (uint32_t)channel_args->args[i].value.integer); } } else if (0 == strcmp(channel_args->args[i].key, @@ -368,7 +379,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, gpr_log(GPR_ERROR, "%s: must be non-negative", GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER); } else { - push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, (uint32_t)channel_args->args[i].value.integer); } } else if (0 == strcmp(channel_args->args[i].key, @@ -393,7 +404,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, gpr_log(GPR_ERROR, "%s: must be non-negative", GRPC_ARG_MAX_METADATA_SIZE); } else { - push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, (uint32_t)channel_args->args[i].value.integer); } } @@ -444,6 +455,9 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { if (!t->closed) { + if (grpc_http_write_state_trace) { + gpr_log(GPR_DEBUG, "W:%p close transport", t); + } t->closed = 1; connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "close_transport"); @@ -513,6 +527,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, &s->global.received_trailing_metadata); grpc_chttp2_data_parser_init(&s->parsing.data_parser); gpr_slice_buffer_init(&s->writing.flow_controlled_buffer); + s->global.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); REF_TRANSPORT(t, "stream"); @@ -589,7 +604,8 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer_destroy( &s->global.received_trailing_metadata); gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer); - GRPC_ERROR_UNREF(s->global.removal_error); + GRPC_ERROR_UNREF(s->global.read_closed_error); + GRPC_ERROR_UNREF(s->global.write_closed_error); UNREF_TRANSPORT(exec_ctx, t, "stream"); @@ -633,6 +649,36 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream( * LOCK MANAGEMENT */ +static const char *write_state_name(grpc_chttp2_write_state state) { + switch (state) { + case GRPC_CHTTP2_WRITING_INACTIVE: + return "INACTIVE"; + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + return "REQUESTED[p=0]"; + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + return "REQUESTED[p=1]"; + case GRPC_CHTTP2_WRITE_SCHEDULED: + return "SCHEDULED"; + case GRPC_CHTTP2_WRITING: + return "WRITING"; + case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: + return "WRITING[p=1]"; + case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: + return "WRITING[p=0]"; + } + GPR_UNREACHABLE_CODE(return "UNKNOWN"); +} + +static void set_write_state(grpc_chttp2_transport *t, + grpc_chttp2_write_state state, const char *reason) { + if (grpc_http_write_state_trace) { + gpr_log(GPR_DEBUG, "W:%p %s -> %s because %s", t, + write_state_name(t->executor.write_state), write_state_name(state), + reason); + } + t->executor.write_state = state; +} + static void finish_global_actions(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_chttp2_executor_action_header *hdr; @@ -641,13 +687,6 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx, GPR_TIMER_BEGIN("finish_global_actions", 0); for (;;) { - if (!t->executor.writing_active && !t->closed && - grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) { - t->executor.writing_active = 1; - REF_TRANSPORT(t, "writing"); - prevent_endpoint_shutdown(t); - grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL); - } check_read_ops(exec_ctx, &t->global); gpr_mu_lock(&t->executor.mu); @@ -668,8 +707,28 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx, continue; } else { t->executor.global_active = false; + switch (t->executor.write_state) { + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "unlocking"); + REF_TRANSPORT(t, "initiate_writing"); + gpr_mu_unlock(&t->executor.mu); + grpc_exec_ctx_sched( + exec_ctx, &t->initiate_writing, GRPC_ERROR_NONE, + t->ep != NULL ? grpc_endpoint_get_workqueue(t->ep) : NULL); + break; + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + start_writing(exec_ctx, t); + gpr_mu_unlock(&t->executor.mu); + break; + case GRPC_CHTTP2_WRITING_INACTIVE: + case GRPC_CHTTP2_WRITING: + case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: + case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: + case GRPC_CHTTP2_WRITE_SCHEDULED: + gpr_mu_unlock(&t->executor.mu); + break; + } } - gpr_mu_unlock(&t->executor.mu); break; } @@ -740,16 +799,118 @@ void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, * OUTPUT PROCESSING */ -void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global) { +void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport_global *transport_global, + bool covered_by_poller, const char *reason) { + /* Perform state checks, and transition to a scheduled state if appropriate. + Each time we finish the global lock execution, we check if we need to + write. If we do: + - (if there is a poller surrounding the write) schedule + initiate_writing, which locks and calls initiate_writing_locked to... + - call start_writing, which verifies (under the global lock) that there + are things that need to be written by calling + grpc_chttp2_unlocking_check_writes, and if so schedules writing_action + against the current exec_ctx, to be executed OUTSIDE of the global lock + - eventually writing_action results in grpc_chttp2_terminate_writing being + called, which re-takes the global lock, updates state, checks if we need + to do *another* write immediately, and if so loops back to + start_writing. + + Current problems: + - too much lock entry/exiting + - the writing thread can become stuck indefinitely (punt through the + workqueue periodically to fix) */ + + grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); + switch (t->executor.write_state) { + case GRPC_CHTTP2_WRITING_INACTIVE: + set_write_state(t, covered_by_poller + ? GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER + : GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, + reason); + break; + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + /* nothing to do: write already requested */ + break; + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + if (covered_by_poller) { + /* upgrade to note poller is available to cover the write */ + set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, reason); + } + break; + case GRPC_CHTTP2_WRITE_SCHEDULED: + /* nothing to do: write already scheduled */ + break; + case GRPC_CHTTP2_WRITING: + set_write_state(t, + covered_by_poller ? GRPC_CHTTP2_WRITING_STALE_WITH_POLLER + : GRPC_CHTTP2_WRITING_STALE_NO_POLLER, + reason); + break; + case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: + /* nothing to do: write already requested */ + break; + case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: + if (covered_by_poller) { + /* upgrade to note poller is available to cover the write */ + set_write_state(t, GRPC_CHTTP2_WRITING_STALE_WITH_POLLER, reason); + } + break; + } +} + +static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { + GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED || + t->executor.write_state == GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER); + if (!t->closed && + grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) { + set_write_state(t, GRPC_CHTTP2_WRITING, "start_writing"); + REF_TRANSPORT(t, "writing"); + prevent_endpoint_shutdown(t); + grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL); + } else { + if (t->closed) { + set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, + "start_writing:transport_closed"); + } else { + set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, + "start_writing:nothing_to_write"); + } + end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write")); + if (t->ep && !t->endpoint_reading) { + destroy_endpoint(exec_ctx, t); + } + } +} + +static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, + void *arg_ignored) { + start_writing(exec_ctx, t); + UNREF_TRANSPORT(exec_ctx, t, "initiate_writing"); +} + +static void initiate_writing(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_run_with_global_lock(exec_ctx, arg, NULL, initiate_writing_locked, + NULL, 0); +} + +void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport_global *transport_global, + grpc_chttp2_stream_global *stream_global, + bool covered_by_poller, const char *reason) { if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed && grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) { GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing"); + grpc_chttp2_initiate_write(exec_ctx, transport_global, covered_by_poller, + reason); } } -static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, - uint32_t value) { +static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, + grpc_chttp2_setting_id id, uint32_t value) { const grpc_chttp2_setting_parameters *sp = &grpc_chttp2_settings_parameters[id]; uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value); @@ -760,9 +921,22 @@ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, if (use_value != t->global.settings[GRPC_LOCAL_SETTINGS][id]) { t->global.settings[GRPC_LOCAL_SETTINGS][id] = use_value; t->global.dirtied_local_settings = 1; + grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "push_setting"); } } +static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, grpc_error *error) { + grpc_chttp2_stream_global *stream_global; + while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global, + &stream_global)) { + fail_pending_writes(exec_ctx, &t->global, stream_global, + GRPC_ERROR_REF(error)); + GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes"); + } + GRPC_ERROR_UNREF(error); +} + static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s_ignored, @@ -777,24 +951,32 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing); - grpc_chttp2_stream_global *stream_global; - while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global, - &stream_global)) { - fail_pending_writes(exec_ctx, &t->global, stream_global, - GRPC_ERROR_REF(error)); - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes"); + end_waiting_for_write(exec_ctx, t, error); + + switch (t->executor.write_state) { + case GRPC_CHTTP2_WRITING_INACTIVE: + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + case GRPC_CHTTP2_WRITE_SCHEDULED: + GPR_UNREACHABLE_CODE(break); + case GRPC_CHTTP2_WRITING: + set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "terminate_writing"); + break; + case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: + set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, + "terminate_writing"); + break; + case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: + set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, + "terminate_writing"); + break; } - /* leave the writing flag up on shutdown to prevent further writes in - unlock() - from starting */ - t->executor.writing_active = 0; if (t->ep && !t->endpoint_reading) { destroy_endpoint(exec_ctx, t); } UNREF_TRANSPORT(exec_ctx, t, "writing"); - GRPC_ERROR_UNREF(error); } void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx, @@ -877,7 +1059,8 @@ static void maybe_start_some_streams( stream_global->id, STREAM_FROM_GLOBAL(stream_global)); stream_global->in_stream_map = true; transport_global->concurrent_stream_count++; - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, true, + "new_stream"); } /* cancel out streams that will never be started */ while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID && @@ -988,6 +1171,11 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, const size_t metadata_peer_limit = transport_global->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; + if (transport_global->is_client) { + stream_global->deadline = + gpr_time_min(stream_global->deadline, + stream_global->send_initial_metadata->deadline); + } if (metadata_size > metadata_peer_limit) { cancel_from_api( exec_ctx, transport_global, stream_global, @@ -1012,9 +1200,11 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, maybe_start_some_streams(exec_ctx, transport_global); } else { GPR_ASSERT(stream_global->id != 0); - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, + true, "op.send_initial_metadata"); } } else { + stream_global->send_trailing_metadata = NULL; grpc_chttp2_complete_closure_step( exec_ctx, transport_global, stream_global, &stream_global->send_initial_metadata_finished, @@ -1036,7 +1226,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, } else { stream_global->send_message = op->send_message; if (stream_global->id != 0) { - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, + true, "op.send_message"); } } } @@ -1069,6 +1260,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (stream_global->write_closed) { + stream_global->send_trailing_metadata = NULL; grpc_chttp2_complete_closure_step( exec_ctx, transport_global, stream_global, &stream_global->send_trailing_metadata_finished, @@ -1079,7 +1271,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, } else if (stream_global->id != 0) { /* TODO(ctiller): check if there's flow control for any outstanding bytes before going writable */ - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, + true, "op.send_trailing_metadata"); } } } @@ -1100,8 +1293,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, (stream_global->incoming_frames.head == NULL || stream_global->incoming_frames.head->is_tail)) { incoming_byte_stream_update_flow_control( - transport_global, stream_global, transport_global->stream_lookahead, - 0); + exec_ctx, transport_global, stream_global, + transport_global->stream_lookahead, 0); } grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } @@ -1129,7 +1322,8 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, sizeof(*op)); } -static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) { +static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, + grpc_closure *on_recv) { grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p)); p->next = &t->global.pings; p->prev = p->next->prev; @@ -1144,6 +1338,7 @@ static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) { p->id[7] = (uint8_t)(t->global.ping_counter & 0xff); p->on_recv = on_recv; gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id)); + grpc_chttp2_initiate_write(exec_ctx, &t->global, true, "send_ping"); } static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -1203,6 +1398,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, close_transport = grpc_chttp2_has_streams(t) ? GRPC_ERROR_NONE : GRPC_ERROR_CREATE("GOAWAY sent"); + grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "goaway_sent"); } if (op->set_accept_stream) { @@ -1220,7 +1416,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, } if (op->send_ping) { - send_ping_locked(t, op->send_ping); + send_ping_locked(exec_ctx, t, op->send_ping); } if (close_transport != GRPC_ERROR_NONE) { @@ -1366,7 +1562,7 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, GRPC_ERROR_UNREF(error); } -static void status_codes_from_error(grpc_error *error, +static void status_codes_from_error(grpc_error *error, gpr_timespec deadline, grpc_chttp2_error_code *http2_error, grpc_status_code *grpc_status) { intptr_t ip_http; @@ -1386,8 +1582,8 @@ static void status_codes_from_error(grpc_error *error, if (have_grpc) { *grpc_status = (grpc_status_code)ip_grpc; } else if (have_http) { - *grpc_status = - grpc_chttp2_http2_error_to_grpc_status((grpc_chttp2_error_code)ip_http); + *grpc_status = grpc_chttp2_http2_error_to_grpc_status( + (grpc_chttp2_error_code)ip_http, deadline); } else { *grpc_status = GRPC_STATUS_INTERNAL; } @@ -1400,13 +1596,16 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx, if (!stream_global->read_closed || !stream_global->write_closed) { grpc_status_code grpc_status; grpc_chttp2_error_code http_error; - status_codes_from_error(due_to_error, &http_error, &grpc_status); + status_codes_from_error(due_to_error, stream_global->deadline, &http_error, + &grpc_status); if (stream_global->id != 0) { gpr_slice_buffer_add( &transport_global->qbuf, grpc_chttp2_rst_stream_create(stream_global->id, (uint32_t)http_error, &stream_global->stats.outgoing)); + grpc_chttp2_initiate_write(exec_ctx, transport_global, false, + "rst_stream"); } const char *msg = @@ -1466,10 +1665,39 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, } } +static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) { + if (error == GRPC_ERROR_NONE) return; + for (size_t i = 0; i < *nrefs; i++) { + if (error == refs[i]) { + return; + } + } + refs[*nrefs] = error; + ++*nrefs; +} + +static grpc_error *removal_error(grpc_error *extra_error, + grpc_chttp2_stream_global *stream_global) { + grpc_error *refs[3]; + size_t nrefs = 0; + add_error(stream_global->read_closed_error, refs, &nrefs); + add_error(stream_global->write_closed_error, refs, &nrefs); + add_error(extra_error, refs, &nrefs); + grpc_error *error = GRPC_ERROR_NONE; + if (nrefs > 0) { + error = GRPC_ERROR_CREATE_REFERENCING("Failed due to stream removal", refs, + nrefs); + } + GRPC_ERROR_UNREF(extra_error); + return error; +} + static void fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, grpc_error *error) { + error = removal_error(error, stream_global); + stream_global->send_message = NULL; grpc_chttp2_complete_closure_step( exec_ctx, transport_global, stream_global, &stream_global->send_initial_metadata_finished, GRPC_ERROR_REF(error)); @@ -1492,14 +1720,17 @@ void grpc_chttp2_mark_stream_closed( } grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); if (close_reads && !stream_global->read_closed) { + stream_global->read_closed_error = GRPC_ERROR_REF(error); stream_global->read_closed = true; stream_global->published_initial_metadata = true; stream_global->published_trailing_metadata = true; decrement_active_streams_locked(exec_ctx, transport_global, stream_global); } if (close_writes && !stream_global->write_closed) { + stream_global->write_closed_error = GRPC_ERROR_REF(error); stream_global->write_closed = true; - if (TRANSPORT_FROM_GLOBAL(transport_global)->executor.writing_active) { + if (TRANSPORT_FROM_GLOBAL(transport_global)->executor.write_state != + GRPC_CHTTP2_WRITING_INACTIVE) { GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes"); grpc_chttp2_list_add_closed_waiting_for_writing(transport_global, stream_global); @@ -1509,7 +1740,6 @@ void grpc_chttp2_mark_stream_closed( } } if (stream_global->read_closed && stream_global->write_closed) { - stream_global->removal_error = GRPC_ERROR_REF(error); if (stream_global->id != 0 && TRANSPORT_FROM_GLOBAL(transport_global)->executor.parsing_active) { grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global, @@ -1517,7 +1747,8 @@ void grpc_chttp2_mark_stream_closed( } else { if (stream_global->id != 0) { remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global), - stream_global->id, GRPC_ERROR_REF(error)); + stream_global->id, + removal_error(GRPC_ERROR_REF(error), stream_global)); } GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2"); } @@ -1536,7 +1767,8 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, uint32_t len = 0; grpc_status_code grpc_status; grpc_chttp2_error_code http_error; - status_codes_from_error(error, &http_error, &grpc_status); + status_codes_from_error(error, stream_global->deadline, &http_error, + &grpc_status); GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100); @@ -1641,6 +1873,8 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, 1, error); + grpc_chttp2_initiate_write(exec_ctx, transport_global, false, + "close_from_api"); } typedef struct { @@ -1670,8 +1904,14 @@ static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, } /** update window from a settings change */ +typedef struct { + grpc_chttp2_transport *t; + grpc_exec_ctx *exec_ctx; +} update_global_window_args; + static void update_global_window(void *args, uint32_t id, void *stream) { - grpc_chttp2_transport *t = args; + update_global_window_args *a = args; + grpc_chttp2_transport *t = a->t; grpc_chttp2_stream *s = stream; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_stream_global *stream_global = &s->global; @@ -1685,7 +1925,8 @@ static void update_global_window(void *args, uint32_t id, void *stream) { is_zero = stream_global->outgoing_window <= 0; if (was_zero && !is_zero) { - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_become_writable(a->exec_ctx, transport_global, stream_global, + true, "update_global_window"); } } @@ -1764,6 +2005,7 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; + grpc_error *err = GRPC_ERROR_NONE; GPR_TIMER_BEGIN("reading_action.parse", 0); size_t i = 0; grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE, @@ -1772,15 +2014,13 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing, t->read_buffer.slices[i]); }; - if (i != t->read_buffer.count) { + if (errors[1] == GRPC_ERROR_NONE) { + err = GRPC_ERROR_REF(error); + } else { errors[2] = try_http_parsing(exec_ctx, t); + err = GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors, + GPR_ARRAY_SIZE(errors)); } - grpc_error *err = - errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE && - errors[2] == GRPC_ERROR_NONE - ? GRPC_ERROR_NONE - : GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors, - GPR_ARRAY_SIZE(errors)); for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) { GRPC_ERROR_UNREF(errors[i]); } @@ -1794,14 +2034,19 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; /* copy parsing qbuf to global qbuf */ - gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf); + if (t->parsing.qbuf.count > 0) { + gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf); + grpc_chttp2_initiate_write(exec_ctx, transport_global, false, + "parsing_qbuf"); + } /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); transport_global->concurrent_stream_count = (uint32_t)grpc_chttp2_stream_map_size(&t->parsing_stream_map); if (transport_parsing->initial_window_update != 0) { + update_global_window_args args = {t, exec_ctx}; grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, - update_global_window, t); + update_global_window, &args); transport_parsing->initial_window_update = 0; } /* handle higher level things */ @@ -1824,7 +2069,7 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, GPR_ASSERT(stream_global->write_closed); GPR_ASSERT(stream_global->read_closed); remove_stream(exec_ctx, t, stream_global->id, - GRPC_ERROR_REF(stream_global->removal_error)); + removal_error(GRPC_ERROR_NONE, stream_global)); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2"); } @@ -1847,11 +2092,12 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, } drop_connection(exec_ctx, t, GRPC_ERROR_REF(error)); t->endpoint_reading = 0; - if (!t->executor.writing_active && t->ep) { - grpc_endpoint_destroy(exec_ctx, t->ep); - t->ep = NULL; - /* safe as we still have a ref for read */ - UNREF_TRANSPORT(exec_ctx, t, "disconnect"); + if (grpc_http_write_state_trace) { + gpr_log(GPR_DEBUG, "R:%p -> 0 ws=%s", t, + write_state_name(t->executor.write_state)); + } + if (t->executor.write_state == GRPC_CHTTP2_WRITING_INACTIVE && t->ep) { + destroy_endpoint(exec_ctx, t); } } else if (!t->closed) { keep_reading = true; @@ -1935,7 +2181,7 @@ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx, } static void incoming_byte_stream_update_flow_control( - grpc_chttp2_transport_global *transport_global, + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, size_t max_size_hint, size_t have_already) { uint32_t max_recv_bytes; @@ -1970,7 +2216,8 @@ static void incoming_byte_stream_update_flow_control( add_max_recv_bytes); grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global, stream_global); - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, + false, "read_incoming_stream"); } } @@ -1992,8 +2239,9 @@ static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_global *stream_global = &bs->stream->global; if (bs->is_tail) { - incoming_byte_stream_update_flow_control( - transport_global, stream_global, arg->max_size_hint, bs->slices.length); + incoming_byte_stream_update_flow_control(exec_ctx, transport_global, + stream_global, arg->max_size_hint, + bs->slices.length); } if (bs->slices.count > 0) { *arg->slice = gpr_slice_buffer_take_first(&bs->slices); @@ -2177,7 +2425,7 @@ static char *format_flowctl_context_var(const char *context, const char *var, if (context == NULL) { *scope = NULL; gpr_asprintf(&buf, "%s(%" PRId64 ")", var, val); - result = gpr_leftpad(buf, ' ', 40); + result = gpr_leftpad(buf, ' ', 60); gpr_free(buf); return result; } @@ -2190,7 +2438,7 @@ static char *format_flowctl_context_var(const char *context, const char *var, gpr_free(tmp); } gpr_asprintf(&buf, "%s.%s(%" PRId64 ")", underscore_pos + 1, var, val); - result = gpr_leftpad(buf, ' ', 40); + result = gpr_leftpad(buf, ' ', 60); gpr_free(buf); return result; } @@ -2223,7 +2471,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase, tmp_phase = gpr_leftpad(phase, ' ', 8); tmp_scope1 = gpr_leftpad(scope1, ' ', 11); - gpr_asprintf(&prefix, "FLOW %s: %s %s ", phase, clisvr, scope1); + gpr_asprintf(&prefix, "FLOW %s: %s %s ", tmp_phase, clisvr, scope1); gpr_free(tmp_phase); gpr_free(tmp_scope1); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index b5180c6fc8..e1dcf5262a 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -305,6 +305,22 @@ typedef struct grpc_chttp2_executor_action_header { void *arg; } grpc_chttp2_executor_action_header; +typedef enum { + /** no writing activity */ + GRPC_CHTTP2_WRITING_INACTIVE, + /** write has been requested, but not scheduled yet */ + GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, + GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, + /** write has been requested and scheduled against the workqueue */ + GRPC_CHTTP2_WRITE_SCHEDULED, + /** write has been initiated after being reaped from the workqueue */ + GRPC_CHTTP2_WRITING, + /** write has been initiated, AND another write needs to be started once it's + done */ + GRPC_CHTTP2_WRITING_STALE_WITH_POLLER, + GRPC_CHTTP2_WRITING_STALE_NO_POLLER, +} grpc_chttp2_write_state; + struct grpc_chttp2_transport { grpc_transport base; /* must be first */ gpr_refcount refs; @@ -319,10 +335,10 @@ struct grpc_chttp2_transport { /** is a thread currently in the global lock */ bool global_active; - /** is a thread currently writing */ - bool writing_active; /** is a thread currently parsing */ bool parsing_active; + /** write execution state of the transport */ + grpc_chttp2_write_state write_state; grpc_chttp2_executor_action_header *pending_actions_head; grpc_chttp2_executor_action_header *pending_actions_tail; @@ -342,7 +358,8 @@ struct grpc_chttp2_transport { /** global state for reading/writing */ grpc_chttp2_transport_global global; /** state only accessible by the chain of execution that - set writing_active=1 */ + set writing_state >= GRPC_WRITING, and only by the writing closure + chain. */ grpc_chttp2_transport_writing writing; /** state only accessible by the chain of execution that set parsing_active=1 */ @@ -363,6 +380,8 @@ struct grpc_chttp2_transport { grpc_closure reading_action; /** closure to actually do parsing */ grpc_closure parsing_action; + /** closure to initiate writing */ + grpc_closure initiate_writing; /** incoming read bytes */ gpr_slice_buffer read_buffer; @@ -436,8 +455,10 @@ typedef struct { bool seen_error; bool exceeded_metadata_size; - /** the error that resulted in this stream being removed */ - grpc_error *removal_error; + /** the error that resulted in this stream being read-closed */ + grpc_error *read_closed_error; + /** the error that resulted in this stream being write-closed */ + grpc_error *write_closed_error; bool published_initial_metadata; bool published_trailing_metadata; @@ -447,6 +468,8 @@ typedef struct { grpc_chttp2_incoming_metadata_buffer received_trailing_metadata; grpc_chttp2_incoming_frame_queue incoming_frames; + + gpr_timespec deadline; } grpc_chttp2_stream_global; typedef struct { @@ -512,15 +535,20 @@ struct grpc_chttp2_stream { }; /** Transport writing call flow: - chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes - are required; - if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the - writes. - Once writes have been completed (meaning another write could potentially be - started), - grpc_chttp2_terminate_writing is called. This will call - grpc_chttp2_cleanup_writing, at which - point the write phase is complete. */ + grpc_chttp2_initiate_write() is called anywhere that we know bytes need to + go out on the wire. + If no other write has been started, a task is enqueued onto our workqueue. + When that task executes, it obtains the global lock, and gathers the data + to write. + The global lock is dropped and we do the syscall to write. + After writing, a follow-up check is made to see if another round of writing + should be performed. + + The actual call chain is documented in the implementation of this function. + */ +void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport_global *transport_global, + bool covered_by_poller, const char *reason); /** Someone is unlocking the transport mutex: check to see if writes are required, and schedule them if so */ @@ -608,9 +636,8 @@ int grpc_chttp2_list_pop_check_read_ops( void grpc_chttp2_list_add_writing_stalled_by_transport( grpc_chttp2_transport_writing *transport_writing, grpc_chttp2_stream_writing *stream_writing); -void grpc_chttp2_list_flush_writing_stalled_by_transport( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing, - bool is_window_available); +bool grpc_chttp2_list_flush_writing_stalled_by_transport( + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing); void grpc_chttp2_list_add_stalled_by_transport( grpc_chttp2_transport_writing *transport_writing, @@ -820,7 +847,9 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, /** add a ref to the stream and add it to the writable list; ref will be dropped in writing.c */ -void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global, - grpc_chttp2_stream_global *stream_global); +void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport_global *transport_global, + grpc_chttp2_stream_global *stream_global, + bool covered_by_poller, const char *reason); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */ diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 991d7729af..e1fc0ddee2 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -154,10 +154,8 @@ void grpc_chttp2_publish_reads( transport_parsing, outgoing_window); is_zero = transport_global->outgoing_window <= 0; if (was_zero && !is_zero) { - while (grpc_chttp2_list_pop_stalled_by_transport(transport_global, - &stream_global)) { - grpc_chttp2_become_writable(transport_global, stream_global); - } + grpc_chttp2_initiate_write(exec_ctx, transport_global, false, + "new_global_flow_control"); } if (transport_parsing->incoming_window < @@ -168,6 +166,8 @@ void grpc_chttp2_publish_reads( announce_incoming_window, announce_bytes); GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing, incoming_window, announce_bytes); + grpc_chttp2_initiate_write(exec_ctx, transport_global, false, + "global incoming window"); } /* for each stream that saw an update, fixup global state */ @@ -190,7 +190,8 @@ void grpc_chttp2_publish_reads( outgoing_window); is_zero = stream_global->outgoing_window <= 0; if (was_zero && !is_zero) { - grpc_chttp2_become_writable(transport_global, stream_global); + grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, + false, "stream.read_flow_control"); } stream_global->max_recv_bytes -= (uint32_t)GPR_MIN( @@ -236,9 +237,10 @@ void grpc_chttp2_publish_reads( GRPC_ERROR_INT_HTTP2_ERROR, &reason); if (has_reason && reason != GRPC_CHTTP2_NO_ERROR) { grpc_status_code status_code = - has_reason ? grpc_chttp2_http2_error_to_grpc_status( - (grpc_chttp2_error_code)reason) - : GRPC_STATUS_INTERNAL; + has_reason + ? grpc_chttp2_http2_error_to_grpc_status( + (grpc_chttp2_error_code)reason, stream_global->deadline) + : GRPC_STATUS_INTERNAL; const char *status_details = grpc_error_string(stream_parsing->forced_close_error); gpr_slice slice_details = gpr_slice_from_copied_string(status_details); diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.c b/src/core/ext/transport/chttp2/transport/status_conversion.c index c42fb9b3a1..5dce2f2d0c 100644 --- a/src/core/ext/transport/chttp2/transport/status_conversion.c +++ b/src/core/ext/transport/chttp2/transport/status_conversion.c @@ -39,6 +39,8 @@ int grpc_chttp2_grpc_status_to_http2_error(grpc_status_code status) { return GRPC_CHTTP2_NO_ERROR; case GRPC_STATUS_CANCELLED: return GRPC_CHTTP2_CANCEL; + case GRPC_STATUS_DEADLINE_EXCEEDED: + return GRPC_CHTTP2_CANCEL; case GRPC_STATUS_RESOURCE_EXHAUSTED: return GRPC_CHTTP2_ENHANCE_YOUR_CALM; case GRPC_STATUS_PERMISSION_DENIED: @@ -51,13 +53,17 @@ int grpc_chttp2_grpc_status_to_http2_error(grpc_status_code status) { } grpc_status_code grpc_chttp2_http2_error_to_grpc_status( - grpc_chttp2_error_code error) { + grpc_chttp2_error_code error, gpr_timespec deadline) { switch (error) { case GRPC_CHTTP2_NO_ERROR: /* should never be received */ return GRPC_STATUS_INTERNAL; case GRPC_CHTTP2_CANCEL: - return GRPC_STATUS_CANCELLED; + /* http2 cancel translates to STATUS_CANCELLED iff deadline hasn't been + * exceeded */ + return gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0 + ? GRPC_STATUS_DEADLINE_EXCEEDED + : GRPC_STATUS_CANCELLED; case GRPC_CHTTP2_ENHANCE_YOUR_CALM: return GRPC_STATUS_RESOURCE_EXHAUSTED; case GRPC_CHTTP2_INADEQUATE_SECURITY: diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.h b/src/core/ext/transport/chttp2/transport/status_conversion.h index e7285e6fd5..953bc9f1e1 100644 --- a/src/core/ext/transport/chttp2/transport/status_conversion.h +++ b/src/core/ext/transport/chttp2/transport/status_conversion.h @@ -41,7 +41,7 @@ grpc_chttp2_error_code grpc_chttp2_grpc_status_to_http2_error( grpc_status_code status); grpc_status_code grpc_chttp2_http2_error_to_grpc_status( - grpc_chttp2_error_code error); + grpc_chttp2_error_code error, gpr_timespec deadline); /* Conversion of HTTP status codes (:status) to grpc status codes */ grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status); diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.c b/src/core/ext/transport/chttp2/transport/stream_lists.c index 8f3ab00e6d..2eb5f5f632 100644 --- a/src/core/ext/transport/chttp2/transport/stream_lists.c +++ b/src/core/ext/transport/chttp2/transport/stream_lists.c @@ -329,6 +329,7 @@ void grpc_chttp2_list_add_writing_stalled_by_transport( grpc_chttp2_transport_writing *transport_writing, grpc_chttp2_stream_writing *stream_writing) { grpc_chttp2_stream *stream = STREAM_FROM_WRITING(stream_writing); + gpr_log(GPR_DEBUG, "writing stalled %d", stream->global.id); if (!stream->included[GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT]) { GRPC_CHTTP2_STREAM_REF(&stream->global, "chttp2_writing_stalled"); } @@ -336,27 +337,28 @@ void grpc_chttp2_list_add_writing_stalled_by_transport( GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT); } -void grpc_chttp2_list_flush_writing_stalled_by_transport( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing, - bool is_window_available) { +bool grpc_chttp2_list_flush_writing_stalled_by_transport( + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing) { grpc_chttp2_stream *stream; + bool out = false; grpc_chttp2_transport *transport = TRANSPORT_FROM_WRITING(transport_writing); while (stream_list_pop(transport, &stream, GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) { - if (is_window_available) { - grpc_chttp2_become_writable(&transport->global, &stream->global); - } else { - grpc_chttp2_list_add_stalled_by_transport(transport_writing, - &stream->writing); - } + gpr_log(GPR_DEBUG, "move %d from writing stalled to just stalled", + stream->global.id); + grpc_chttp2_list_add_stalled_by_transport(transport_writing, + &stream->writing); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &stream->global, "chttp2_writing_stalled"); + out = true; } + return out; } void grpc_chttp2_list_add_stalled_by_transport( grpc_chttp2_transport_writing *transport_writing, grpc_chttp2_stream_writing *stream_writing) { + gpr_log(GPR_DEBUG, "stalled %d", stream_writing->id); stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), STREAM_FROM_WRITING(stream_writing), GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index b19f5f068d..e0d87725e9 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -75,9 +75,13 @@ int grpc_chttp2_unlocking_check_writes( GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window, transport_global, outgoing_window); - bool is_window_available = transport_writing->outgoing_window > 0; - grpc_chttp2_list_flush_writing_stalled_by_transport( - exec_ctx, transport_writing, is_window_available); + if (transport_writing->outgoing_window > 0) { + while (grpc_chttp2_list_pop_stalled_by_transport(transport_global, + &stream_global)) { + grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, + false, "transport.read_flow_control"); + } + } /* for each grpc_chttp2_stream that's become writable, frame it's data (according to available window sizes) and add to the output buffer */ @@ -331,6 +335,12 @@ void grpc_chttp2_cleanup_writing( grpc_chttp2_stream_writing *stream_writing; grpc_chttp2_stream_global *stream_global; + if (grpc_chttp2_list_flush_writing_stalled_by_transport(exec_ctx, + transport_writing)) { + grpc_chttp2_initiate_write(exec_ctx, transport_global, false, + "resume_stalled_stream"); + } + while (grpc_chttp2_list_pop_written_stream( transport_global, transport_writing, &stream_global, &stream_writing)) { if (stream_writing->sent_initial_metadata) { diff --git a/src/core/lib/http/parser.c.orig b/src/core/lib/http/parser.c.orig deleted file mode 100644 index 74d90fd8bf..0000000000 --- a/src/core/lib/http/parser.c.orig +++ /dev/null @@ -1,357 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/http/parser.h" - -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/useful.h> - -int grpc_http1_trace = 0; - -static char *buf2str(void *buffer, size_t length) { - char *out = gpr_malloc(length + 1); - memcpy(out, buffer, length); - out[length] = 0; - return out; -} - -static grpc_error *handle_response_line(grpc_http_parser *parser) { - uint8_t *beg = parser->cur_line; - uint8_t *cur = beg; - uint8_t *end = beg + parser->cur_line_length; - - if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'"); - if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'"); - if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'"); - if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'"); - if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'"); - if (cur == end || *cur++ != '1') return GRPC_ERROR_CREATE("Expected '1'"); - if (cur == end || *cur++ != '.') return GRPC_ERROR_CREATE("Expected '.'"); - if (cur == end || *cur < '0' || *cur++ > '1') { - return GRPC_ERROR_CREATE("Expected HTTP/1.0 or HTTP/1.1"); - } - if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '"); - if (cur == end || *cur < '1' || *cur++ > '9') - return GRPC_ERROR_CREATE("Expected status code"); - if (cur == end || *cur < '0' || *cur++ > '9') - return GRPC_ERROR_CREATE("Expected status code"); - if (cur == end || *cur < '0' || *cur++ > '9') - return GRPC_ERROR_CREATE("Expected status code"); - parser->http.response->status = - (cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0'); - if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '"); - - /* we don't really care about the status code message */ - - return GRPC_ERROR_NONE; -} - -static grpc_error *handle_request_line(grpc_http_parser *parser) { - uint8_t *beg = parser->cur_line; - uint8_t *cur = beg; - uint8_t *end = beg + parser->cur_line_length; - uint8_t vers_major = 0; - uint8_t vers_minor = 0; - - while (cur != end && *cur++ != ' ') - ; - if (cur == end) return GRPC_ERROR_CREATE("No method on HTTP request line"); - parser->http.request->method = buf2str(beg, (size_t)(cur - beg - 1)); - - beg = cur; - while (cur != end && *cur++ != ' ') - ; - if (cur == end) return GRPC_ERROR_CREATE("No path on HTTP request line"); - parser->http.request->path = buf2str(beg, (size_t)(cur - beg - 1)); - - if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'"); - if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'"); - if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'"); - if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'"); - if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'"); - vers_major = (uint8_t)(*cur++ - '1' + 1); - ++cur; - if (cur == end) - return GRPC_ERROR_CREATE("End of line in HTTP version string"); - vers_minor = (uint8_t)(*cur++ - '1' + 1); - - if (vers_major == 1) { - if (vers_minor == 0) { - parser->http.request->version = GRPC_HTTP_HTTP10; - } else if (vers_minor == 1) { - parser->http.request->version = GRPC_HTTP_HTTP11; - } else { - return GRPC_ERROR_CREATE( - "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); - } - } else if (vers_major == 2) { - if (vers_minor == 0) { - parser->http.request->version = GRPC_HTTP_HTTP20; - } else { - return GRPC_ERROR_CREATE( - "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); - } - } else { - return GRPC_ERROR_CREATE("Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); - } - - return GRPC_ERROR_NONE; -} - -static grpc_error *handle_first_line(grpc_http_parser *parser) { - switch (parser->type) { - case GRPC_HTTP_REQUEST: - return handle_request_line(parser); - case GRPC_HTTP_RESPONSE: - return handle_response_line(parser); - } - GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here")); -} - -static grpc_error *add_header(grpc_http_parser *parser) { - uint8_t *beg = parser->cur_line; - uint8_t *cur = beg; - uint8_t *end = beg + parser->cur_line_length; - size_t *hdr_count = NULL; - grpc_http_header **hdrs = NULL; - grpc_http_header hdr = {NULL, NULL}; - grpc_error *error = GRPC_ERROR_NONE; - - GPR_ASSERT(cur != end); - - if (*cur == ' ' || *cur == '\t') { - error = GRPC_ERROR_CREATE("Continued header lines not supported yet"); - goto done; - } - - while (cur != end && *cur != ':') { - cur++; - } - if (cur == end) { -<<<<<<< HEAD - error = GRPC_ERROR_CREATE("Didn't find ':' in header string"); - goto done; -======= - if (grpc_http1_trace) { - gpr_log(GPR_ERROR, "Didn't find ':' in header string"); - } - goto error; ->>>>>>> a709afe241d8b264a1c326315f757b4a8d330207 - } - GPR_ASSERT(cur >= beg); - hdr.key = buf2str(beg, (size_t)(cur - beg)); - cur++; /* skip : */ - - while (cur != end && (*cur == ' ' || *cur == '\t')) { - cur++; - } - GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length); - hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length); - - switch (parser->type) { - case GRPC_HTTP_RESPONSE: - hdr_count = &parser->http.response->hdr_count; - hdrs = &parser->http.response->hdrs; - break; - case GRPC_HTTP_REQUEST: - hdr_count = &parser->http.request->hdr_count; - hdrs = &parser->http.request->hdrs; - break; - } - - if (*hdr_count == parser->hdr_capacity) { - parser->hdr_capacity = - GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2); - *hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs)); - } - (*hdrs)[(*hdr_count)++] = hdr; - -done: - if (error != GRPC_ERROR_NONE) { - gpr_free(hdr.key); - gpr_free(hdr.value); - } - return error; -} - -static grpc_error *finish_line(grpc_http_parser *parser) { - grpc_error *err; - switch (parser->state) { - case GRPC_HTTP_FIRST_LINE: - err = handle_first_line(parser); - if (err != GRPC_ERROR_NONE) return err; - parser->state = GRPC_HTTP_HEADERS; - break; - case GRPC_HTTP_HEADERS: - if (parser->cur_line_length == parser->cur_line_end_length) { - parser->state = GRPC_HTTP_BODY; - break; - } - err = add_header(parser); - if (err != GRPC_ERROR_NONE) { - return err; - } - break; - case GRPC_HTTP_BODY: - GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here")); - } - - parser->cur_line_length = 0; - return GRPC_ERROR_NONE; -} - -static grpc_error *addbyte_body(grpc_http_parser *parser, uint8_t byte) { - size_t *body_length = NULL; - char **body = NULL; - - if (parser->type == GRPC_HTTP_RESPONSE) { - body_length = &parser->http.response->body_length; - body = &parser->http.response->body; - } else if (parser->type == GRPC_HTTP_REQUEST) { - body_length = &parser->http.request->body_length; - body = &parser->http.request->body; - } else { - GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here")); - } - - if (*body_length == parser->body_capacity) { - parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2); - *body = gpr_realloc((void *)*body, parser->body_capacity); - } - (*body)[*body_length] = (char)byte; - (*body_length)++; - - return GRPC_ERROR_NONE; -} - -static bool check_line(grpc_http_parser *parser) { - if (parser->cur_line_length >= 2 && - parser->cur_line[parser->cur_line_length - 2] == '\r' && - parser->cur_line[parser->cur_line_length - 1] == '\n') { - return true; - } - - // HTTP request with \n\r line termiantors. - else if (parser->cur_line_length >= 2 && - parser->cur_line[parser->cur_line_length - 2] == '\n' && - parser->cur_line[parser->cur_line_length - 1] == '\r') { - return true; - } - - // HTTP request with only \n line terminators. - else if (parser->cur_line_length >= 1 && - parser->cur_line[parser->cur_line_length - 1] == '\n') { - parser->cur_line_end_length = 1; - return true; - } - - return false; -} - -static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) { - switch (parser->state) { - case GRPC_HTTP_FIRST_LINE: - case GRPC_HTTP_HEADERS: - if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) { - if (grpc_http1_trace) - gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded", - GRPC_HTTP_PARSER_MAX_HEADER_LENGTH); - return 0; - } - parser->cur_line[parser->cur_line_length] = byte; - parser->cur_line_length++; - if (check_line(parser)) { - return finish_line(parser); - } else { - return GRPC_ERROR_NONE; - } - GPR_UNREACHABLE_CODE(return 0); - case GRPC_HTTP_BODY: - return addbyte_body(parser, byte); - } - GPR_UNREACHABLE_CODE(return 0); -} - -void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type, - void *request_or_response) { - memset(parser, 0, sizeof(*parser)); - parser->state = GRPC_HTTP_FIRST_LINE; - parser->type = type; - parser->http.request_or_response = request_or_response; - parser->cur_line_end_length = 2; -} - -void grpc_http_parser_destroy(grpc_http_parser *parser) {} - -void grpc_http_request_destroy(grpc_http_request *request) { - size_t i; - gpr_free(request->body); - for (i = 0; i < request->hdr_count; i++) { - gpr_free(request->hdrs[i].key); - gpr_free(request->hdrs[i].value); - } - gpr_free(request->hdrs); - gpr_free(request->method); - gpr_free(request->path); -} - -void grpc_http_response_destroy(grpc_http_response *response) { - size_t i; - gpr_free(response->body); - for (i = 0; i < response->hdr_count; i++) { - gpr_free(response->hdrs[i].key); - gpr_free(response->hdrs[i].value); - } - gpr_free(response->hdrs); -} - -grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) { - size_t i; - - for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) { - grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i]); - if (err != GRPC_ERROR_NONE) return err; - } - - return GRPC_ERROR_NONE; -} - -grpc_error *grpc_http_parser_eof(grpc_http_parser *parser) { - if (parser->state != GRPC_HTTP_BODY) { - return GRPC_ERROR_CREATE("Did not finish headers"); - } - return GRPC_ERROR_NONE; -} diff --git a/src/core/lib/iomgr/endpoint.c b/src/core/lib/iomgr/endpoint.c index 1ab3733d38..f901fcf962 100644 --- a/src/core/lib/iomgr/endpoint.c +++ b/src/core/lib/iomgr/endpoint.c @@ -65,3 +65,7 @@ void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) { char* grpc_endpoint_get_peer(grpc_endpoint* ep) { return ep->vtable->get_peer(ep); } + +grpc_workqueue* grpc_endpoint_get_workqueue(grpc_endpoint* ep) { + return ep->vtable->get_workqueue(ep); +} diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h index f9808bbda1..894efc0b23 100644 --- a/src/core/lib/iomgr/endpoint.h +++ b/src/core/lib/iomgr/endpoint.h @@ -51,6 +51,7 @@ struct grpc_endpoint_vtable { gpr_slice_buffer *slices, grpc_closure *cb); void (*write)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, gpr_slice_buffer *slices, grpc_closure *cb); + grpc_workqueue *(*get_workqueue)(grpc_endpoint *ep); void (*add_to_pollset)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset *pollset); void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, @@ -69,6 +70,9 @@ void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, char *grpc_endpoint_get_peer(grpc_endpoint *ep); +/* Retrieve a reference to the workqueue associated with this endpoint */ +grpc_workqueue *grpc_endpoint_get_workqueue(grpc_endpoint *ep); + /* Write slices out to the socket. If the connection is ready for more data after the end of the call, it diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index cf0fe736a0..6a63c4d1d1 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -57,6 +57,7 @@ #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/block_annotate.h" @@ -113,9 +114,7 @@ struct grpc_fd { grpc_closure *read_closure; grpc_closure *write_closure; - /* The polling island to which this fd belongs to and the mutex protecting the - the field */ - gpr_mu pi_mu; + /* The polling island to which this fd belongs to (protected by mu) */ struct polling_island *polling_island; struct grpc_fd *freelist_next; @@ -152,16 +151,17 @@ static void fd_global_shutdown(void); * Polling island Declarations */ -// #define GRPC_PI_REF_COUNT_DEBUG +//#define GRPC_PI_REF_COUNT_DEBUG #ifdef GRPC_PI_REF_COUNT_DEBUG #define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__) -#define PI_UNREF(p, r) pi_unref_dbg((p), (r), __FILE__, __LINE__) +#define PI_UNREF(exec_ctx, p, r) \ + pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__) #else /* defined(GRPC_PI_REF_COUNT_DEBUG) */ #define PI_ADD_REF(p, r) pi_add_ref((p)) -#define PI_UNREF(p, r) pi_unref((p)) +#define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p)) #endif /* !defined(GPRC_PI_REF_COUNT_DEBUG) */ @@ -172,7 +172,7 @@ typedef struct polling_island { Once the ref count becomes zero, this structure is destroyed which means we should ensure that there is never a scenario where a PI_ADD_REF() is racing with a PI_UNREF() that just made the ref_count zero. */ - gpr_refcount ref_count; + gpr_atm ref_count; /* Pointer to the polling_island this merged into. * merged_to value is only set once in polling_island's lifetime (and that too @@ -184,6 +184,9 @@ typedef struct polling_island { * (except mu and ref_count) are invalid and must be ignored. */ gpr_atm merged_to; + /* The workqueue associated with this polling island */ + grpc_workqueue *workqueue; + /* The fd of the underlying epoll set */ int epoll_fd; @@ -191,11 +194,6 @@ typedef struct polling_island { size_t fd_cnt; size_t fd_capacity; grpc_fd **fds; - - /* Polling islands that are no longer needed are kept in a freelist so that - they can be reused. This field points to the next polling island in the - free list */ - struct polling_island *next_free; } polling_island; /******************************************************************************* @@ -253,13 +251,14 @@ struct grpc_pollset_set { * Common helpers */ -static void append_error(grpc_error **composite, grpc_error *error, +static bool append_error(grpc_error **composite, grpc_error *error, const char *desc) { - if (error == GRPC_ERROR_NONE) return; + if (error == GRPC_ERROR_NONE) return true; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE(desc); } *composite = grpc_error_add_child(*composite, error); + return false; } /******************************************************************************* @@ -275,11 +274,8 @@ static void append_error(grpc_error **composite, grpc_error *error, threads that woke up MUST NOT call grpc_wakeup_fd_consume_wakeup() */ static grpc_wakeup_fd polling_island_wakeup_fd; -/* Polling island freelist */ -static gpr_mu g_pi_freelist_mu; -static polling_island *g_pi_freelist = NULL; - -static void polling_island_delete(); /* Forward declaration */ +/* Forward declaration */ +static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi); #ifdef GRPC_TSAN /* Currently TSAN may incorrectly flag data races between epoll_ctl and @@ -293,28 +289,35 @@ gpr_atm g_epoll_sync; #endif /* defined(GRPC_TSAN) */ #ifdef GRPC_PI_REF_COUNT_DEBUG -void pi_add_ref(polling_island *pi); -void pi_unref(polling_island *pi); +static void pi_add_ref(polling_island *pi); +static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi); -void pi_add_ref_dbg(polling_island *pi, char *reason, char *file, int line) { - long old_cnt = gpr_atm_acq_load(&(pi->ref_count.count)); +static void pi_add_ref_dbg(polling_island *pi, char *reason, char *file, + int line) { + long old_cnt = gpr_atm_acq_load(&pi->ref_count); pi_add_ref(pi); gpr_log(GPR_DEBUG, "Add ref pi: %p, old: %ld -> new:%ld (%s) - (%s, %d)", (void *)pi, old_cnt, old_cnt + 1, reason, file, line); } -void pi_unref_dbg(polling_island *pi, char *reason, char *file, int line) { - long old_cnt = gpr_atm_acq_load(&(pi->ref_count.count)); - pi_unref(pi); +static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi, + char *reason, char *file, int line) { + long old_cnt = gpr_atm_acq_load(&pi->ref_count); + pi_unref(exec_ctx, pi); gpr_log(GPR_DEBUG, "Unref pi: %p, old:%ld -> new:%ld (%s) - (%s, %d)", (void *)pi, old_cnt, (old_cnt - 1), reason, file, line); } #endif -void pi_add_ref(polling_island *pi) { gpr_ref(&pi->ref_count); } +static void pi_add_ref(polling_island *pi) { + gpr_atm_no_barrier_fetch_add(&pi->ref_count, 1); +} -void pi_unref(polling_island *pi) { - /* If ref count went to zero, delete the polling island. +static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi) { + /* If ref count went to one, we're back to just the workqueue owning a ref. + Unref the workqueue to break the loop. + + If ref count went to zero, delete the polling island. Note that this deletion not be done under a lock. Once the ref count goes to zero, we are guaranteed that no one else holds a reference to the polling island (and that there is no racing pi_add_ref() call either). @@ -322,12 +325,20 @@ void pi_unref(polling_island *pi) { Also, if we are deleting the polling island and the merged_to field is non-empty, we should remove a ref to the merged_to polling island */ - if (gpr_unref(&pi->ref_count)) { - polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); - polling_island_delete(pi); - if (next != NULL) { - PI_UNREF(next, "pi_delete"); /* Recursive call */ + switch (gpr_atm_full_fetch_add(&pi->ref_count, -1)) { + case 2: /* last external ref: the only one now owned is by the workqueue */ + GRPC_WORKQUEUE_UNREF(exec_ctx, pi->workqueue, "polling_island"); + break; + case 1: { + polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); + polling_island_delete(exec_ctx, pi); + if (next != NULL) { + PI_UNREF(exec_ctx, next, "pi_delete"); /* Recursive call */ + } + break; } + case 0: + GPR_UNREACHABLE_CODE(return ); } } @@ -462,69 +473,68 @@ static void polling_island_remove_fd_locked(polling_island *pi, grpc_fd *fd, } /* Might return NULL in case of an error */ -static polling_island *polling_island_create(grpc_fd *initial_fd, +static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx, + grpc_fd *initial_fd, grpc_error **error) { polling_island *pi = NULL; - char *err_msg; const char *err_desc = "polling_island_create"; - /* Try to get one from the polling island freelist */ - gpr_mu_lock(&g_pi_freelist_mu); - if (g_pi_freelist != NULL) { - pi = g_pi_freelist; - g_pi_freelist = g_pi_freelist->next_free; - pi->next_free = NULL; - } - gpr_mu_unlock(&g_pi_freelist_mu); + *error = GRPC_ERROR_NONE; - /* Create new polling island if we could not get one from the free list */ - if (pi == NULL) { - pi = gpr_malloc(sizeof(*pi)); - gpr_mu_init(&pi->mu); - pi->fd_cnt = 0; - pi->fd_capacity = 0; - pi->fds = NULL; - } + pi = gpr_malloc(sizeof(*pi)); + gpr_mu_init(&pi->mu); + pi->fd_cnt = 0; + pi->fd_capacity = 0; + pi->fds = NULL; + pi->epoll_fd = -1; + pi->workqueue = NULL; - gpr_ref_init(&pi->ref_count, 0); + gpr_atm_rel_store(&pi->ref_count, 0); gpr_atm_rel_store(&pi->merged_to, (gpr_atm)NULL); pi->epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (pi->epoll_fd < 0) { - gpr_asprintf(&err_msg, "epoll_create1 failed with error %d (%s)", errno, - strerror(errno)); - append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); - gpr_free(err_msg); - } else { - polling_island_add_wakeup_fd_locked(pi, &grpc_global_wakeup_fd, error); - pi->next_free = NULL; + append_error(error, GRPC_OS_ERROR(errno, "epoll_create1"), err_desc); + goto done; + } - if (initial_fd != NULL) { - /* Lock the polling island here just in case we got this structure from - the freelist and the polling island lock was not released yet (by the - code that adds the polling island to the freelist) */ - gpr_mu_lock(&pi->mu); - polling_island_add_fds_locked(pi, &initial_fd, 1, true, error); - gpr_mu_unlock(&pi->mu); - } + polling_island_add_wakeup_fd_locked(pi, &grpc_global_wakeup_fd, error); + + if (initial_fd != NULL) { + polling_island_add_fds_locked(pi, &initial_fd, 1, true, error); + } + + if (append_error(error, grpc_workqueue_create(exec_ctx, &pi->workqueue), + err_desc) && + *error == GRPC_ERROR_NONE) { + polling_island_add_fds_locked(pi, &pi->workqueue->wakeup_read_fd, 1, true, + error); + GPR_ASSERT(pi->workqueue->wakeup_read_fd->polling_island == NULL); + pi->workqueue->wakeup_read_fd->polling_island = pi; + PI_ADD_REF(pi, "fd"); } +done: + if (*error != GRPC_ERROR_NONE) { + if (pi->workqueue != NULL) { + GRPC_WORKQUEUE_UNREF(exec_ctx, pi->workqueue, "polling_island"); + } + polling_island_delete(exec_ctx, pi); + pi = NULL; + } return pi; } -static void polling_island_delete(polling_island *pi) { +static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi) { GPR_ASSERT(pi->fd_cnt == 0); - gpr_atm_rel_store(&pi->merged_to, (gpr_atm)NULL); - - close(pi->epoll_fd); - pi->epoll_fd = -1; - - gpr_mu_lock(&g_pi_freelist_mu); - pi->next_free = g_pi_freelist; - g_pi_freelist = pi; - gpr_mu_unlock(&g_pi_freelist_mu); + if (pi->epoll_fd >= 0) { + close(pi->epoll_fd); + } + gpr_mu_destroy(&pi->mu); + gpr_free(pi->fds); + gpr_free(pi); } /* Attempts to gets the last polling island in the linked list (liked by the @@ -704,9 +714,6 @@ static polling_island *polling_island_merge(polling_island *p, static grpc_error *polling_island_global_init() { grpc_error *error = GRPC_ERROR_NONE; - gpr_mu_init(&g_pi_freelist_mu); - g_pi_freelist = NULL; - error = grpc_wakeup_fd_init(&polling_island_wakeup_fd); if (error == GRPC_ERROR_NONE) { error = grpc_wakeup_fd_wakeup(&polling_island_wakeup_fd); @@ -716,18 +723,6 @@ static grpc_error *polling_island_global_init() { } static void polling_island_global_shutdown() { - polling_island *next; - gpr_mu_lock(&g_pi_freelist_mu); - gpr_mu_unlock(&g_pi_freelist_mu); - while (g_pi_freelist != NULL) { - next = g_pi_freelist->next_free; - gpr_mu_destroy(&g_pi_freelist->mu); - gpr_free(g_pi_freelist->fds); - gpr_free(g_pi_freelist); - g_pi_freelist = next; - } - gpr_mu_destroy(&g_pi_freelist_mu); - grpc_wakeup_fd_destroy(&polling_island_wakeup_fd); } @@ -845,7 +840,6 @@ static grpc_fd *fd_create(int fd, const char *name) { if (new_fd == NULL) { new_fd = gpr_malloc(sizeof(grpc_fd)); gpr_mu_init(&new_fd->mu); - gpr_mu_init(&new_fd->pi_mu); } /* Note: It is not really needed to get the new_fd->mu lock here. If this is a @@ -896,6 +890,7 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, const char *reason) { bool is_fd_closed = false; grpc_error *error = GRPC_ERROR_NONE; + polling_island *unref_pi = NULL; gpr_mu_lock(&fd->mu); fd->on_done_closure = on_done; @@ -923,21 +918,26 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - Unlock the latest polling island - Set fd->polling_island to NULL (but remove the ref on the polling island before doing this.) */ - gpr_mu_lock(&fd->pi_mu); if (fd->polling_island != NULL) { polling_island *pi_latest = polling_island_lock(fd->polling_island); polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error); gpr_mu_unlock(&pi_latest->mu); - PI_UNREF(fd->polling_island, "fd_orphan"); + unref_pi = fd->polling_island; fd->polling_island = NULL; } - gpr_mu_unlock(&fd->pi_mu); grpc_exec_ctx_sched(exec_ctx, fd->on_done_closure, error, NULL); gpr_mu_unlock(&fd->mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ + if (unref_pi != NULL) { + /* Unref stale polling island here, outside the fd lock above. + The polling island owns a workqueue which owns an fd, and unreffing + inside the lock can cause an eventual lock loop that makes TSAN very + unhappy. */ + PI_UNREF(exec_ctx, unref_pi, "fd_orphan"); + } GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error)); } @@ -1037,6 +1037,17 @@ static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_mu_unlock(&fd->mu); } +static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { + gpr_mu_lock(&fd->mu); + grpc_workqueue *workqueue = NULL; + if (fd->polling_island != NULL) { + workqueue = + GRPC_WORKQUEUE_REF(fd->polling_island->workqueue, "get_workqueue"); + } + gpr_mu_unlock(&fd->mu); + return workqueue; +} + /******************************************************************************* * Pollset Definitions */ @@ -1227,9 +1238,10 @@ static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { gpr_mu_unlock(&fd->mu); } -static void pollset_release_polling_island(grpc_pollset *ps, char *reason) { +static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx, + grpc_pollset *ps, char *reason) { if (ps->polling_island != NULL) { - PI_UNREF(ps->polling_island, reason); + PI_UNREF(exec_ctx, ps->polling_island, reason); } ps->polling_island = NULL; } @@ -1242,7 +1254,7 @@ static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, pollset->finish_shutdown_called = true; /* Release the ref and set pollset->polling_island to NULL */ - pollset_release_polling_island(pollset, "ps_shutdown"); + pollset_release_polling_island(exec_ctx, pollset, "ps_shutdown"); grpc_exec_ctx_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE, NULL); } @@ -1281,7 +1293,7 @@ static void pollset_reset(grpc_pollset *pollset) { pollset->finish_shutdown_called = false; pollset->kicked_without_pollers = false; pollset->shutdown_done = NULL; - pollset_release_polling_island(pollset, "ps_reset"); + GPR_ASSERT(pollset->polling_island == NULL); } #define GRPC_EPOLL_MAX_EVENTS 1000 @@ -1309,7 +1321,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, this function (i.e pollset_work_and_unlock()) is called */ if (pollset->polling_island == NULL) { - pollset->polling_island = polling_island_create(NULL, error); + pollset->polling_island = polling_island_create(exec_ctx, NULL, error); if (pollset->polling_island == NULL) { GPR_TIMER_END("pollset_work_and_unlock", 0); return; /* Fatal error. We cannot continue */ @@ -1329,7 +1341,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, /* Always do PI_ADD_REF before PI_UNREF because PI_UNREF may cause the polling island to be deleted */ PI_ADD_REF(pi, "ps"); - PI_UNREF(pollset->polling_island, "ps"); + PI_UNREF(exec_ctx, pollset->polling_island, "ps"); pollset->polling_island = pi; } @@ -1400,7 +1412,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, that we got before releasing the polling island lock). This is because pollset->polling_island pointer might get udpated in other parts of the code when there is an island merge while we are doing epoll_wait() above */ - PI_UNREF(pi, "ps_work"); + PI_UNREF(exec_ctx, pi, "ps_work"); GPR_TIMER_END("pollset_work_and_unlock", 0); } @@ -1517,10 +1529,11 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_error *error = GRPC_ERROR_NONE; gpr_mu_lock(&pollset->mu); - gpr_mu_lock(&fd->pi_mu); + gpr_mu_lock(&fd->mu); polling_island *pi_new = NULL; +retry: /* 1) If fd->polling_island and pollset->polling_island are both non-NULL and * equal, do nothing. * 2) If fd->polling_island and pollset->polling_island are both NULL, create @@ -1535,15 +1548,44 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, * polling_island fields in both fd and pollset to point to the merged * polling island. */ + + if (fd->orphaned) { + gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&pollset->mu); + /* early out */ + return; + } + if (fd->polling_island == pollset->polling_island) { pi_new = fd->polling_island; if (pi_new == NULL) { - pi_new = polling_island_create(fd, &error); - - GRPC_POLLING_TRACE( - "pollset_add_fd: Created new polling island. pi_new: %p (fd: %d, " - "pollset: %p)", - (void *)pi_new, fd->fd, (void *)pollset); + /* Unlock before creating a new polling island: the polling island will + create a workqueue which creates a file descriptor, and holding an fd + lock here can eventually cause a loop to appear to TSAN (making it + unhappy). We don't think it's a real loop (there's an epoch point where + that loop possibility disappears), but the advantages of keeping TSAN + happy outweigh any performance advantage we might have by keeping the + lock held. */ + gpr_mu_unlock(&fd->mu); + pi_new = polling_island_create(exec_ctx, fd, &error); + gpr_mu_lock(&fd->mu); + /* Need to reverify any assumptions made between the initial lock and + getting to this branch: if they've changed, we need to throw away our + work and figure things out again. */ + if (fd->polling_island != NULL) { + GRPC_POLLING_TRACE( + "pollset_add_fd: Raced creating new polling island. pi_new: %p " + "(fd: %d, pollset: %p)", + (void *)pi_new, fd->fd, (void *)pollset); + PI_ADD_REF(pi_new, "dance_of_destruction"); + PI_UNREF(exec_ctx, pi_new, "dance_of_destruction"); + goto retry; + } else { + GRPC_POLLING_TRACE( + "pollset_add_fd: Created new polling island. pi_new: %p (fd: %d, " + "pollset: %p)", + (void *)pi_new, fd->fd, (void *)pollset); + } } } else if (fd->polling_island == NULL) { pi_new = polling_island_lock(pollset->polling_island); @@ -1579,7 +1621,7 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, if (fd->polling_island != pi_new) { PI_ADD_REF(pi_new, "fd"); if (fd->polling_island != NULL) { - PI_UNREF(fd->polling_island, "fd"); + PI_UNREF(exec_ctx, fd->polling_island, "fd"); } fd->polling_island = pi_new; } @@ -1587,13 +1629,15 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, if (pollset->polling_island != pi_new) { PI_ADD_REF(pi_new, "ps"); if (pollset->polling_island != NULL) { - PI_UNREF(pollset->polling_island, "ps"); + PI_UNREF(exec_ctx, pollset->polling_island, "ps"); } pollset->polling_island = pi_new; } - gpr_mu_unlock(&fd->pi_mu); + gpr_mu_unlock(&fd->mu); gpr_mu_unlock(&pollset->mu); + + GRPC_LOG_IF_ERROR("pollset_add_fd", error); } /******************************************************************************* @@ -1744,9 +1788,9 @@ static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, void *grpc_fd_get_polling_island(grpc_fd *fd) { polling_island *pi; - gpr_mu_lock(&fd->pi_mu); + gpr_mu_lock(&fd->mu); pi = fd->polling_island; - gpr_mu_unlock(&fd->pi_mu); + gpr_mu_unlock(&fd->mu); return pi; } @@ -1794,6 +1838,7 @@ static const grpc_event_engine_vtable vtable = { .fd_notify_on_read = fd_notify_on_read, .fd_notify_on_write = fd_notify_on_write, .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, + .fd_get_workqueue = fd_get_workqueue, .pollset_init = pollset_init, .pollset_shutdown = pollset_shutdown, diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c index 9e306af5fa..c2107e5e39 100644 --- a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c +++ b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c @@ -725,6 +725,8 @@ static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher, GRPC_FD_UNREF(fd, "poll"); } +static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { return NULL; } + /******************************************************************************* * pollset_posix.c */ @@ -2006,6 +2008,7 @@ static const grpc_event_engine_vtable vtable = { .fd_notify_on_read = fd_notify_on_read, .fd_notify_on_write = fd_notify_on_write, .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, + .fd_get_workqueue = fd_get_workqueue, .pollset_init = pollset_init, .pollset_shutdown = pollset_shutdown, diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index 45c0a5e954..4b593f4b2c 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -617,6 +617,8 @@ static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher, GRPC_FD_UNREF(fd, "poll"); } +static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { return NULL; } + /******************************************************************************* * pollset_posix.c */ @@ -1234,6 +1236,7 @@ static const grpc_event_engine_vtable vtable = { .fd_notify_on_read = fd_notify_on_read, .fd_notify_on_write = fd_notify_on_write, .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, + .fd_get_workqueue = fd_get_workqueue, .pollset_init = pollset_init, .pollset_shutdown = pollset_shutdown, diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index a3c1e9db9a..6536672685 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -148,6 +148,10 @@ grpc_fd *grpc_fd_create(int fd, const char *name) { return g_event_engine->fd_create(fd, name); } +grpc_workqueue *grpc_fd_get_workqueue(grpc_fd *fd) { + return g_event_engine->fd_get_workqueue(fd); +} + int grpc_fd_wrapped_fd(grpc_fd *fd) { return g_event_engine->fd_wrapped_fd(fd); } diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index 579c84ef70..c2aa1756ea 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -56,6 +56,7 @@ typedef struct grpc_event_engine_vtable { void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure); bool (*fd_is_shutdown)(grpc_fd *fd); + grpc_workqueue *(*fd_get_workqueue)(grpc_fd *fd); grpc_pollset *(*fd_get_read_notifier_pollset)(grpc_exec_ctx *exec_ctx, grpc_fd *fd); @@ -107,6 +108,9 @@ const char *grpc_get_poll_strategy_name(); This takes ownership of closing fd. */ grpc_fd *grpc_fd_create(int fd, const char *name); +/* Get a workqueue that's associated with this fd */ +grpc_workqueue *grpc_fd_get_workqueue(grpc_fd *fd); + /* Return the wrapped fd, or -1 if it has been released or closed. */ int grpc_fd_wrapped_fd(grpc_fd *fd); diff --git a/src/core/lib/iomgr/exec_ctx.c b/src/core/lib/iomgr/exec_ctx.c index c44aafcddf..ac7785ec13 100644 --- a/src/core/lib/iomgr/exec_ctx.c +++ b/src/core/lib/iomgr/exec_ctx.c @@ -37,6 +37,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> +#include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx) { @@ -85,14 +86,17 @@ void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) { void grpc_exec_ctx_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error, grpc_workqueue *offload_target_or_null) { - GPR_ASSERT(offload_target_or_null == NULL); - grpc_closure_list_append(&exec_ctx->closure_list, closure, error); + if (offload_target_or_null == NULL) { + grpc_closure_list_append(&exec_ctx->closure_list, closure, error); + } else { + grpc_workqueue_enqueue(exec_ctx, offload_target_or_null, closure, error); + GRPC_WORKQUEUE_UNREF(exec_ctx, offload_target_or_null, "exec_ctx_sched"); + } } void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx, grpc_closure_list *list, grpc_workqueue *offload_target_or_null) { - GPR_ASSERT(offload_target_or_null == NULL); grpc_closure_list_move(list, &exec_ctx->closure_list); } diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 38f27d9b13..917f332f03 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -93,7 +93,11 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx); /** Finish any pending work for a grpc_exec_ctx. Must be called before * the instance is destroyed, or work may be lost. */ void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx); -/** Add a closure to be executed at the next flush/finish point */ +/** Add a closure to be executed in the future. + If \a offload_target_or_null is NULL, the closure will be executed at the + next exec_ctx.{finish,flush} point. + If \a offload_target_or_null is non-NULL, the closure will be scheduled + against the workqueue, and a reference to the workqueue will be consumed. */ void grpc_exec_ctx_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error, grpc_workqueue *offload_target_or_null); diff --git a/src/core/lib/iomgr/iomgr.c b/src/core/lib/iomgr/iomgr.c index 89292a153e..d67d388b8c 100644 --- a/src/core/lib/iomgr/iomgr.c +++ b/src/core/lib/iomgr/iomgr.c @@ -45,6 +45,7 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr_internal.h" +#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" @@ -62,6 +63,7 @@ void grpc_iomgr_init(void) { grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC)); g_root_object.next = g_root_object.prev = &g_root_object; g_root_object.name = "root"; + grpc_network_status_init(); grpc_iomgr_platform_init(); } @@ -140,6 +142,7 @@ void grpc_iomgr_shutdown(void) { grpc_iomgr_platform_shutdown(); grpc_exec_ctx_global_shutdown(); + grpc_network_status_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); } diff --git a/src/core/lib/iomgr/network_status_tracker.c b/src/core/lib/iomgr/network_status_tracker.c index 38a1c9b7d4..b4bb7e3cf7 100644 --- a/src/core/lib/iomgr/network_status_tracker.c +++ b/src/core/lib/iomgr/network_status_tracker.c @@ -42,10 +42,16 @@ typedef struct endpoint_ll_node { static endpoint_ll_node *head = NULL; static gpr_mu g_endpoint_mutex; -static bool g_init_done = false; -void grpc_initialize_network_status_monitor() { - g_init_done = true; +void grpc_network_status_shutdown(void) { + if (head != NULL) { + gpr_log(GPR_ERROR, + "Memory leaked as all network endpoints were not shut down"); + } + gpr_mu_destroy(&g_endpoint_mutex); +} + +void grpc_network_status_init(void) { gpr_mu_init(&g_endpoint_mutex); // TODO(makarandd): Install callback with OS to monitor network status. } @@ -60,9 +66,6 @@ void grpc_destroy_network_status_monitor() { } void grpc_network_status_register_endpoint(grpc_endpoint *ep) { - if (!g_init_done) { - grpc_initialize_network_status_monitor(); - } gpr_mu_lock(&g_endpoint_mutex); if (head == NULL) { head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node)); diff --git a/src/core/lib/iomgr/network_status_tracker.h b/src/core/lib/iomgr/network_status_tracker.h index 74a1aa8135..67cb645f44 100644 --- a/src/core/lib/iomgr/network_status_tracker.h +++ b/src/core/lib/iomgr/network_status_tracker.h @@ -35,7 +35,11 @@ #define GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H #include "src/core/lib/iomgr/endpoint.h" +void grpc_network_status_init(void); +void grpc_network_status_shutdown(void); + void grpc_network_status_register_endpoint(grpc_endpoint *ep); void grpc_network_status_unregister_endpoint(grpc_endpoint *ep); void grpc_network_status_shutdown_all_endpoints(); + #endif /* GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H */ diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index 2ab45e33ce..ec21e03944 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -284,7 +284,7 @@ static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, } /* returns true if done, false if pending; if returning true, *error is set */ -#define MAX_WRITE_IOVEC 16 +#define MAX_WRITE_IOVEC 1024 static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; @@ -450,9 +450,19 @@ static char *tcp_get_peer(grpc_endpoint *ep) { return gpr_strdup(tcp->peer_string); } -static const grpc_endpoint_vtable vtable = { - tcp_read, tcp_write, tcp_add_to_pollset, tcp_add_to_pollset_set, - tcp_shutdown, tcp_destroy, tcp_get_peer}; +static grpc_workqueue *tcp_get_workqueue(grpc_endpoint *ep) { + grpc_tcp *tcp = (grpc_tcp *)ep; + return grpc_fd_get_workqueue(tcp->em_fd); +} + +static const grpc_endpoint_vtable vtable = {tcp_read, + tcp_write, + tcp_get_workqueue, + tcp_add_to_pollset, + tcp_add_to_pollset_set, + tcp_shutdown, + tcp_destroy, + tcp_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, const char *peer_string) { diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index d3803c3bd0..cb2ff782d6 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -491,7 +491,8 @@ static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) { } for (unsigned i = 0; i < count; i++) { - int fd, port; + int fd = -1; + int port = -1; grpc_dualstack_mode dsmode; err = grpc_create_dualstack_socket(&listener->addr.sockaddr, SOCK_STREAM, 0, &dsmode, &fd); diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c index 37ab59021e..35054c42b5 100644 --- a/src/core/lib/iomgr/tcp_windows.c +++ b/src/core/lib/iomgr/tcp_windows.c @@ -389,9 +389,16 @@ static char *win_get_peer(grpc_endpoint *ep) { return gpr_strdup(tcp->peer_string); } -static grpc_endpoint_vtable vtable = { - win_read, win_write, win_add_to_pollset, win_add_to_pollset_set, - win_shutdown, win_destroy, win_get_peer}; +static grpc_workqueue *win_get_workqueue(grpc_endpoint *ep) { return NULL; } + +static grpc_endpoint_vtable vtable = {win_read, + win_write, + win_get_workqueue, + win_add_to_pollset, + win_add_to_pollset_set, + win_shutdown, + win_destroy, + win_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index 1ebccf2ee2..48032412a2 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -60,6 +60,7 @@ #include <grpc/support/string_util.h> #include <grpc/support/sync.h> #include <grpc/support/time.h> +#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -128,7 +129,7 @@ grpc_udp_server *grpc_udp_server_create(void) { } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { - grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1, NULL); + grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); gpr_mu_destroy(&s->mu); gpr_cv_destroy(&s->cv); @@ -138,7 +139,7 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { } static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, - bool success) { + grpc_error *error) { grpc_udp_server *s = server; gpr_mu_lock(&s->mu); s->destroyed_ports++; @@ -217,14 +218,23 @@ static int prepare_socket(int fd, const struct sockaddr *addr, goto error; } - if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1)) { - gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd, - strerror(errno)); + if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno)); + goto error; + } + if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno)); + goto error; } - if (grpc_set_socket_ip_pktinfo_if_possible(fd) && - addr->sa_family == AF_INET6) { - grpc_set_socket_ipv6_recvpktinfo_if_possible(fd); + if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set ip_pktinfo."); + goto error; + } else if (addr->sa_family == AF_INET6) { + if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo."); + goto error; + } } GPR_ASSERT(addr_len < ~(socklen_t)0); @@ -241,13 +251,13 @@ static int prepare_socket(int fd, const struct sockaddr *addr, goto error; } - if (!grpc_set_socket_sndbuf(fd, buffer_size_bytes)) { + if (grpc_set_socket_sndbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes", buffer_size_bytes); goto error; } - if (!grpc_set_socket_rcvbuf(fd, buffer_size_bytes)) { + if (grpc_set_socket_rcvbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes", buffer_size_bytes); goto error; @@ -263,10 +273,10 @@ error: } /* event manager callback when reads are ready */ -static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) { +static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { server_port *sp = arg; - if (!success) { + if (error != GRPC_ERROR_NONE) { gpr_mu_lock(&sp->server->mu); if (0 == --sp->server->active_ports) { gpr_mu_unlock(&sp->server->mu); @@ -369,7 +379,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr, /* Try listening on IPv6 first. */ addr = (struct sockaddr *)&wild6; addr_len = sizeof(wild6); - fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode); + // TODO(rjshade): Test and propagate the returned grpc_error*: + grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd); allocated_port1 = add_socket_to_server(s, fd, addr, addr_len, read_cb, orphan_cb); if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { @@ -384,7 +395,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr, addr_len = sizeof(wild4); } - fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode); + // TODO(rjshade): Test and propagate the returned grpc_error*: + grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd); if (fd < 0) { gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); } diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h index 5cc40eea50..7156e490d7 100644 --- a/src/core/lib/iomgr/workqueue.h +++ b/src/core/lib/iomgr/workqueue.h @@ -38,6 +38,7 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/iomgr/pollset_set.h" #ifdef GPR_POSIX_SOCKET #include "src/core/lib/iomgr/workqueue_posix.h" @@ -49,35 +50,45 @@ /* grpc_workqueue is forward declared in exec_ctx.h */ -/** Create a work queue */ -grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, - grpc_workqueue **workqueue); - +/* Deprecated: do not use. + This has *already* been removed in a future commit. */ void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); -#define GRPC_WORKQUEUE_REFCOUNT_DEBUG +/* Reference counting functions. Use the macro's always + (GRPC_WORKQUEUE_{REF,UNREF}). + + Pass in a descriptive reason string for reffing/unreffing as the last + argument to each macro. When GRPC_WORKQUEUE_REFCOUNT_DEBUG is defined, that + string will be printed alongside the refcount. When it is not defined, the + string will be discarded at compilation time. */ + +//#define GRPC_WORKQUEUE_REFCOUNT_DEBUG #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG #define GRPC_WORKQUEUE_REF(p, r) \ - grpc_workqueue_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_WORKQUEUE_UNREF(cl, p, r) \ - grpc_workqueue_unref((cl), (p), __FILE__, __LINE__, (r)) + (grpc_workqueue_ref((p), __FILE__, __LINE__, (r)), (p)) +#define GRPC_WORKQUEUE_UNREF(exec_ctx, p, r) \ + grpc_workqueue_unref((exec_ctx), (p), __FILE__, __LINE__, (r)) void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason); void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason); #else -#define GRPC_WORKQUEUE_REF(p, r) grpc_workqueue_ref((p)) +#define GRPC_WORKQUEUE_REF(p, r) (grpc_workqueue_ref((p)), (p)) #define GRPC_WORKQUEUE_UNREF(cl, p, r) grpc_workqueue_unref((cl), (p)) void grpc_workqueue_ref(grpc_workqueue *workqueue); void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); #endif -/** Bind this workqueue to a pollset */ -void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx, - grpc_workqueue *workqueue, - grpc_pollset *pollset); +/** Add a work item to a workqueue. Items added to a work queue will be started + in approximately the order they were enqueued, on some thread that may or + may not be the current thread. Successive closures enqueued onto a workqueue + MAY be executed concurrently. + + It is generally more expensive to add a closure to a workqueue than to the + execution context, both in terms of CPU work and in execution latency. -/** Add a work item to a workqueue */ + Use work queues when it's important that other threads be given a chance to + tackle some workload. */ void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, grpc_closure *closure, grpc_error *error); diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index 45e0f6063b..e0d6dac230 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -70,7 +70,7 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, static void workqueue_destroy(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - GPR_ASSERT(grpc_closure_list_empty(workqueue->closure_list)); + grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); grpc_fd_shutdown(exec_ctx, workqueue->wakeup_read_fd); } @@ -100,12 +100,6 @@ void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { } } -void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx, - grpc_workqueue *workqueue, - grpc_pollset *pollset) { - grpc_pollset_add_fd(exec_ctx, pollset, workqueue->wakeup_read_fd); -} - void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { gpr_mu_lock(&workqueue->mu); grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); diff --git a/src/core/lib/iomgr/workqueue_posix.h b/src/core/lib/iomgr/workqueue_posix.h index dcb47e7b59..0f26ba58e2 100644 --- a/src/core/lib/iomgr/workqueue_posix.h +++ b/src/core/lib/iomgr/workqueue_posix.h @@ -50,4 +50,9 @@ struct grpc_workqueue { grpc_closure read_closure; }; +/** Create a work queue. Returns an error if creation fails. If creation + succeeds, sets *workqueue to point to it. */ +grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, + grpc_workqueue **workqueue); + #endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_POSIX_H */ diff --git a/src/core/lib/iomgr/workqueue_windows.c b/src/core/lib/iomgr/workqueue_windows.c index 275f040b1c..23e2dea185 100644 --- a/src/core/lib/iomgr/workqueue_windows.c +++ b/src/core/lib/iomgr/workqueue_windows.c @@ -37,4 +37,26 @@ #include "src/core/lib/iomgr/workqueue.h" +// Minimal implementation of grpc_workqueue for Windows +// Works by directly enqueuing workqueue items onto the current execution +// context, which is at least correct, if not performant or in the spirit of +// workqueues. + +void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} + +#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG +void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, + const char *reason) {} +void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, + const char *file, int line, const char *reason) {} +#else +void grpc_workqueue_ref(grpc_workqueue *workqueue) {} +void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} +#endif + +void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, + grpc_closure *closure, grpc_error *error) { + grpc_exec_ctx_sched(exec_ctx, closure, error, NULL); +} + #endif /* GPR_WINDOWS */ diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index 14ccf72dc9..ed7929aa27 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -176,7 +176,7 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx, calld->creds = grpc_composite_call_credentials_create(channel_call_creds, ctx->creds, NULL); if (calld->creds == NULL) { - bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, + bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, "Incompatible credentials set on channel and call."); return; } @@ -205,7 +205,7 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, char *error_msg; gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", grpc_mdstr_as_c_string(calld->host)); - bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, error_msg); + bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, error_msg); gpr_free(error_msg); } } diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c index 7650d68e89..bc50f9d1b0 100644 --- a/src/core/lib/security/transport/secure_endpoint.c +++ b/src/core/lib/security/transport/secure_endpoint.c @@ -360,11 +360,19 @@ static char *endpoint_get_peer(grpc_endpoint *secure_ep) { return grpc_endpoint_get_peer(ep->wrapped_ep); } -static const grpc_endpoint_vtable vtable = { - endpoint_read, endpoint_write, - endpoint_add_to_pollset, endpoint_add_to_pollset_set, - endpoint_shutdown, endpoint_destroy, - endpoint_get_peer}; +static grpc_workqueue *endpoint_get_workqueue(grpc_endpoint *secure_ep) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + return grpc_endpoint_get_workqueue(ep->wrapped_ep); +} + +static const grpc_endpoint_vtable vtable = {endpoint_read, + endpoint_write, + endpoint_get_workqueue, + endpoint_add_to_pollset, + endpoint_add_to_pollset_set, + endpoint_shutdown, + endpoint_destroy, + endpoint_get_peer}; grpc_endpoint *grpc_secure_endpoint_create( struct tsi_frame_protector *protector, grpc_endpoint *transport, diff --git a/src/core/lib/support/log.c b/src/core/lib/support/log.c index bae0957df7..899f1218b6 100644 --- a/src/core/lib/support/log.c +++ b/src/core/lib/support/log.c @@ -79,17 +79,18 @@ void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print) { void gpr_log_verbosity_init() { char *verbosity = gpr_getenv("GRPC_VERBOSITY"); - if (verbosity == NULL) return; - gpr_atm min_severity_to_print = GPR_LOG_VERBOSITY_UNSET; - if (strcmp(verbosity, "DEBUG") == 0) { - min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG; - } else if (strcmp(verbosity, "INFO") == 0) { - min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO; - } else if (strcmp(verbosity, "ERROR") == 0) { - min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR; + gpr_atm min_severity_to_print = GPR_LOG_SEVERITY_ERROR; + if (verbosity != NULL) { + if (strcmp(verbosity, "DEBUG") == 0) { + min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG; + } else if (strcmp(verbosity, "INFO") == 0) { + min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO; + } else if (strcmp(verbosity, "ERROR") == 0) { + min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR; + } + gpr_free(verbosity); } - gpr_free(verbosity); if ((gpr_atm_no_barrier_load(&g_min_severity_to_print)) == GPR_LOG_VERBOSITY_UNSET) { gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print); diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index e5668be47f..fc9df76dc1 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -259,7 +259,8 @@ grpc_call *grpc_call_create( call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); } } - call->send_deadline = send_deadline; + call->send_deadline = + gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC); GRPC_CHANNEL_INTERNAL_REF(channel, "call"); /* initial refcount dropped by grpc_call_destroy */ grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call, diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c index 2cf6d8890a..6d2b1c4935 100644 --- a/src/core/lib/surface/channel.c +++ b/src/core/lib/surface/channel.c @@ -81,7 +81,7 @@ struct grpc_channel { CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem)) /* the protobuf library will (by default) start warning at 100megs */ -#define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024) +#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024) static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index def6e5068b..2f108af48a 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -73,6 +73,7 @@ typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type; typedef struct requested_call { requested_call_type type; + size_t cq_idx; void *tag; grpc_server *server; grpc_completion_queue *cq_bound_to_call; @@ -206,11 +207,11 @@ struct grpc_server { registered_method *registered_methods; /** one request matcher for unregistered methods */ request_matcher unregistered_request_matcher; - /** free list of available requested_calls indices */ - gpr_stack_lockfree *request_freelist; + /** free list of available requested_calls_per_cq indices */ + gpr_stack_lockfree **request_freelist_per_cq; /** requested call backing data */ - requested_call *requested_calls; - size_t max_requested_calls; + requested_call **requested_calls_per_cq; + int max_requested_calls_per_cq; gpr_atm shutdown_flag; uint8_t shutdown_published; @@ -357,7 +358,8 @@ static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx, for (size_t i = 0; i < server->cq_count; i++) { while ((request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[i])) != -1) { - fail_call(exec_ctx, server, i, &server->requested_calls[request_id], + fail_call(exec_ctx, server, i, + &server->requested_calls_per_cq[i][request_id], GRPC_ERROR_REF(error)); } } @@ -392,12 +394,16 @@ static void server_delete(grpc_exec_ctx *exec_ctx, grpc_server *server) { } for (i = 0; i < server->cq_count; i++) { GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server"); + if (server->started) { + gpr_stack_lockfree_destroy(server->request_freelist_per_cq[i]); + gpr_free(server->requested_calls_per_cq[i]); + } } - gpr_stack_lockfree_destroy(server->request_freelist); + gpr_free(server->request_freelist_per_cq); + gpr_free(server->requested_calls_per_cq); gpr_free(server->cqs); gpr_free(server->pollsets); gpr_free(server->shutdown_tags); - gpr_free(server->requested_calls); gpr_free(server); } @@ -460,11 +466,13 @@ static void done_request_event(grpc_exec_ctx *exec_ctx, void *req, requested_call *rc = req; grpc_server *server = rc->server; - if (rc >= server->requested_calls && - rc < server->requested_calls + server->max_requested_calls) { - GPR_ASSERT(rc - server->requested_calls <= INT_MAX); - gpr_stack_lockfree_push(server->request_freelist, - (int)(rc - server->requested_calls)); + if (rc >= server->requested_calls_per_cq[rc->cq_idx] && + rc < server->requested_calls_per_cq[rc->cq_idx] + + server->max_requested_calls_per_cq) { + GPR_ASSERT(rc - server->requested_calls_per_cq[rc->cq_idx] <= INT_MAX); + gpr_stack_lockfree_push( + server->request_freelist_per_cq[rc->cq_idx], + (int)(rc - server->requested_calls_per_cq[rc->cq_idx])); } else { gpr_free(req); } @@ -540,7 +548,7 @@ static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, calld->state = ACTIVATED; gpr_mu_unlock(&calld->mu_state); publish_call(exec_ctx, server, calld, cq_idx, - &server->requested_calls[request_id]); + &server->requested_calls_per_cq[cq_idx][request_id]); return; /* early out */ } } @@ -979,8 +987,6 @@ void grpc_server_register_non_listening_completion_queue( } grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) { - size_t i; - GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved)); grpc_server *server = gpr_malloc(sizeof(grpc_server)); @@ -998,15 +1004,7 @@ grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) { &server->root_channel_data; /* TODO(ctiller): expose a channel_arg for this */ - server->max_requested_calls = 32768; - server->request_freelist = - gpr_stack_lockfree_create(server->max_requested_calls); - for (i = 0; i < (size_t)server->max_requested_calls; i++) { - gpr_stack_lockfree_push(server->request_freelist, (int)i); - } - server->requested_calls = gpr_malloc(server->max_requested_calls * - sizeof(*server->requested_calls)); - + server->max_requested_calls_per_cq = 32768; server->channel_args = grpc_channel_args_copy(args); return server; @@ -1066,16 +1064,28 @@ void grpc_server_start(grpc_server *server) { server->started = true; size_t pollset_count = 0; server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count); + server->request_freelist_per_cq = + gpr_malloc(sizeof(*server->request_freelist_per_cq) * server->cq_count); + server->requested_calls_per_cq = + gpr_malloc(sizeof(*server->requested_calls_per_cq) * server->cq_count); for (i = 0; i < server->cq_count; i++) { if (!grpc_cq_is_non_listening_server_cq(server->cqs[i])) { server->pollsets[pollset_count++] = grpc_cq_pollset(server->cqs[i]); } + server->request_freelist_per_cq[i] = + gpr_stack_lockfree_create((size_t)server->max_requested_calls_per_cq); + for (int j = 0; j < server->max_requested_calls_per_cq; j++) { + gpr_stack_lockfree_push(server->request_freelist_per_cq[i], j); + } + server->requested_calls_per_cq[i] = + gpr_malloc((size_t)server->max_requested_calls_per_cq * + sizeof(*server->requested_calls_per_cq[i])); } request_matcher_init(&server->unregistered_request_matcher, - server->max_requested_calls, server); + (size_t)server->max_requested_calls_per_cq, server); for (registered_method *rm = server->registered_methods; rm; rm = rm->next) { - request_matcher_init(&rm->request_matcher, server->max_requested_calls, - server); + request_matcher_init(&rm->request_matcher, + (size_t)server->max_requested_calls_per_cq, server); } for (l = server->listeners; l; l = l->next) { @@ -1307,11 +1317,13 @@ static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx, GRPC_ERROR_CREATE("Server Shutdown")); return GRPC_CALL_OK; } - request_id = gpr_stack_lockfree_pop(server->request_freelist); + request_id = gpr_stack_lockfree_pop(server->request_freelist_per_cq[cq_idx]); if (request_id == -1) { /* out of request ids: just fail this one */ fail_call(exec_ctx, server, cq_idx, rc, - GRPC_ERROR_CREATE("Server Shutdown")); + grpc_error_set_int(GRPC_ERROR_CREATE("Out of request ids"), + GRPC_ERROR_INT_LIMIT, + server->max_requested_calls_per_cq)); return GRPC_CALL_OK; } switch (rc->type) { @@ -1322,7 +1334,7 @@ static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx, rm = &rc->data.registered.registered_method->request_matcher; break; } - server->requested_calls[request_id] = *rc; + server->requested_calls_per_cq[cq_idx][request_id] = *rc; gpr_free(rc); if (gpr_stack_lockfree_push(rm->requests_per_cq[cq_idx], request_id)) { /* this was the first queued request: we need to lock and start @@ -1346,7 +1358,7 @@ static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx, calld->state = ACTIVATED; gpr_mu_unlock(&calld->mu_state); publish_call(exec_ctx, server, calld, cq_idx, - &server->requested_calls[request_id]); + &server->requested_calls_per_cq[cq_idx][request_id]); } gpr_mu_lock(&server->mu_call); } @@ -1382,6 +1394,7 @@ grpc_call_error grpc_server_request_call( } grpc_cq_begin_op(cq_for_notification, tag); details->reserved = NULL; + rc->cq_idx = cq_idx; rc->type = BATCH_CALL; rc->server = server; rc->tag = tag; @@ -1430,6 +1443,7 @@ grpc_call_error grpc_server_request_registered_call( goto done; } grpc_cq_begin_op(cq_for_notification, tag); + rc->cq_idx = cq_idx; rc->type = REGISTERED_CALL; rc->server = server; rc->tag = tag; diff --git a/src/core/lib/surface/version.c b/src/core/lib/surface/version.c index 53f3c43854..f0005363d5 100644 --- a/src/core/lib/surface/version.c +++ b/src/core/lib/surface/version.c @@ -36,4 +36,4 @@ #include <grpc/grpc.h> -const char *grpc_version_string(void) { return "0.16.0-dev"; } +const char *grpc_version_string(void) { return "1.0.0-pre1"; } diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c index 054f112127..68d05e3a85 100644 --- a/src/core/lib/transport/connectivity_state.c +++ b/src/core/lib/transport/connectivity_state.c @@ -179,6 +179,9 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, while ((w = tracker->watchers) != NULL) { *w->current = tracker->current_state; tracker->watchers = w->next; + if (grpc_connectivity_state_trace) { + gpr_log(GPR_DEBUG, "NOTIFY: %p", w->notify); + } grpc_exec_ctx_sched(exec_ctx, w->notify, GRPC_ERROR_REF(tracker->current_error), NULL); gpr_free(w); diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index fb4c68ebe4..af04fd4ca6 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -281,6 +281,7 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned, : max_message_size_(max_message_size), started_(false), shutdown_(false), + shutdown_notified_(false), num_running_cb_(0), sync_methods_(new std::list<SyncRequest>), has_generic_service_(false), @@ -462,13 +463,16 @@ void Server::ShutdownInternal(gpr_timespec deadline) { while (num_running_cb_ != 0) { callback_cv_.wait(lock); } + + shutdown_notified_ = true; + shutdown_cv_.notify_all(); } } void Server::Wait() { grpc::unique_lock<grpc::mutex> lock(mu_); - while (num_running_cb_ != 0) { - callback_cv_.wait(lock); + while (started_ && !shutdown_notified_) { + shutdown_cv_.wait(lock); } } diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json index 72c258a91a..34a4e2f1b6 100644 --- a/src/csharp/Grpc.Auth/project.json +++ b/src/csharp/Grpc.Auth/project.json @@ -1,5 +1,5 @@ { - "version": "0.16.0-dev", + "version": "1.0.0-pre1", "title": "gRPC C# Auth", "authors": [ "Google Inc." ], "copyright": "Copyright 2015, Google Inc.", @@ -22,7 +22,7 @@ } }, "dependencies": { - "Grpc.Core": "0.16.0-dev", + "Grpc.Core": "1.0.0-pre1", "Google.Apis.Auth": "1.11.1" }, "frameworks": { diff --git a/src/csharp/Grpc.Core.Tests/project.json b/src/csharp/Grpc.Core.Tests/project.json index f58bcbb515..d4c9a2ef31 100644 --- a/src/csharp/Grpc.Core.Tests/project.json +++ b/src/csharp/Grpc.Core.Tests/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec index 47593f787b..543549eb2d 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.nuspec +++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec @@ -25,11 +25,11 @@ <file src="**\*.cs" target="src" /> <file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" /> <!-- without backslashes in the the source path, nuget won't copy the files --> - <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/build/native/bin/windows_x86/grpc_csharp_ext.dll" /> - <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/build/native/bin/windows_x64/grpc_csharp_ext.dll" /> - <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/build/native/bin/linux_x86/libgrpc_csharp_ext.so" /> - <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/build/native/bin/linux_x64/libgrpc_csharp_ext.so" /> - <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x86/libgrpc_csharp_ext.dylib" /> - <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x64/libgrpc_csharp_ext.dylib" /> + <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x86.dll" /> + <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x64.dll" /> + <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x86.so" /> + <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x64.so" /> + <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x86.dylib" /> + <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x64.dylib" /> </files> </package> diff --git a/src/csharp/Grpc.Core/Grpc.Core.targets b/src/csharp/Grpc.Core/Grpc.Core.targets index 501fc50548..3367d51a80 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.targets +++ b/src/csharp/Grpc.Core/Grpc.Core.targets @@ -1,29 +1,29 @@ <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x86\grpc_csharp_ext.dll"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x86.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link> + <Link>grpc_csharp_ext.x86.dll</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x64\grpc_csharp_ext.dll"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x64.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\windows_x64\grpc_csharp_ext.dll</Link> + <Link>grpc_csharp_ext.x64.dll</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x86\libgrpc_csharp_ext.so"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x86.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\linux_x86\libgrpc_csharp_ext.so</Link> + <Link>libgrpc_csharp_ext.x86.so</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x64\libgrpc_csharp_ext.so"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x64.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link> + <Link>libgrpc_csharp_ext.x64.so</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x86\libgrpc_csharp_ext.dylib"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x86.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link> + <Link>libgrpc_csharp_ext.x86.dylib</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x64\libgrpc_csharp_ext.dylib"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x64.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\macosx_x64\libgrpc_csharp_ext.dylib</Link> + <Link>libgrpc_csharp_ext.x64.dylib</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs index a6d7925816..509baf7cb1 100644 --- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -44,9 +44,6 @@ namespace Grpc.Core.Internal /// </summary> internal sealed class NativeExtension { - const string NativeLibrariesDir = "nativelibs"; - const string DnxStyleNativeLibrariesDir = "../../build/native/bin/"; - static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeExtension>(); static readonly object staticLock = new object(); static volatile NativeExtension instance; @@ -98,20 +95,25 @@ namespace Grpc.Core.Internal private static UnmanagedLibrary Load() { // TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property). - - var libraryFlavor = string.Format("{0}_{1}", GetPlatformString(), GetArchitectureString()); - + // See https://github.com/grpc/grpc/pull/7303 for one option. var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath()); // With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder // alongside the compiled assembly. - var classicPath = Path.Combine(assemblyDirectory, NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); + // With dotnet cli projects, the native libraries (just the required ones) are similarly copied to the built output folder, + // through the magic of Microsoft.NETCore.Platforms. + var classicPath = Path.Combine(assemblyDirectory, GetNativeLibraryFilename()); // DNX-style project.json projects will use Grpc.Core assembly directly in the location where it got restored // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package. - var dnxStylePath = Path.Combine(assemblyDirectory, DnxStyleNativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); - return new UnmanagedLibrary(new string[] {classicPath, dnxStylePath}); + // TODO: Support .NET Core applications, which act slightly differently. We may be okay if "dotnet publish" + // is used, but "dotnet run" leaves the native libraries in-package, while copying assemblies. + string platform = GetPlatformString(); + string relativeDirectory = string.Format("../../runtimes/{0}/native", platform); + var dnxStylePath = Path.Combine(assemblyDirectory, relativeDirectory, GetNativeLibraryFilename()); + string[] paths = new[] { classicPath, dnxStylePath }; + return new UnmanagedLibrary(paths); } private static string GetAssemblyPath() @@ -147,7 +149,7 @@ namespace Grpc.Core.Internal { if (PlatformApis.IsWindows) { - return "windows"; + return "win"; } if (PlatformApis.IsLinux) { @@ -155,7 +157,7 @@ namespace Grpc.Core.Internal } if (PlatformApis.IsMacOSX) { - return "macosx"; + return "osx"; } throw new InvalidOperationException("Unsupported platform."); } @@ -176,17 +178,18 @@ namespace Grpc.Core.Internal // platform specific file name of the extension library private static string GetNativeLibraryFilename() { + string architecture = GetArchitectureString(); if (PlatformApis.IsWindows) { - return "grpc_csharp_ext.dll"; + return string.Format("grpc_csharp_ext.{0}.dll", architecture); } if (PlatformApis.IsLinux) { - return "libgrpc_csharp_ext.so"; + return string.Format("libgrpc_csharp_ext.{0}.so", architecture); } if (PlatformApis.IsMacOSX) { - return "libgrpc_csharp_ext.dylib"; + return string.Format("libgrpc_csharp_ext.{0}.dylib", architecture); } throw new InvalidOperationException("Unsupported platform."); } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 65607ed120..f457c9dbf1 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -159,215 +159,107 @@ namespace Grpc.Core.Internal public NativeMethods(UnmanagedLibrary library) { - if (PlatformApis.IsLinux || PlatformApis.IsMacOSX) - { - this.grpcsharp_init = GetMethodDelegate<Delegates.grpcsharp_init_delegate>(library); - this.grpcsharp_shutdown = GetMethodDelegate<Delegates.grpcsharp_shutdown_delegate>(library); - this.grpcsharp_version_string = GetMethodDelegate<Delegates.grpcsharp_version_string_delegate>(library); - - this.grpcsharp_batch_context_create = GetMethodDelegate<Delegates.grpcsharp_batch_context_create_delegate>(library); - this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate>(library); - this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_length_delegate>(library); - this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate>(library); - this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library); - this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library); - this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library); - this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library); - this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library); - - this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library); - this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library); - - this.grpcsharp_call_cancel = GetMethodDelegate<Delegates.grpcsharp_call_cancel_delegate>(library); - this.grpcsharp_call_cancel_with_status = GetMethodDelegate<Delegates.grpcsharp_call_cancel_with_status_delegate>(library); - this.grpcsharp_call_start_unary = GetMethodDelegate<Delegates.grpcsharp_call_start_unary_delegate>(library); - this.grpcsharp_call_start_client_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_client_streaming_delegate>(library); - this.grpcsharp_call_start_server_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_server_streaming_delegate>(library); - this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_duplex_streaming_delegate>(library); - this.grpcsharp_call_send_message = GetMethodDelegate<Delegates.grpcsharp_call_send_message_delegate>(library); - this.grpcsharp_call_send_close_from_client = GetMethodDelegate<Delegates.grpcsharp_call_send_close_from_client_delegate>(library); - this.grpcsharp_call_send_status_from_server = GetMethodDelegate<Delegates.grpcsharp_call_send_status_from_server_delegate>(library); - this.grpcsharp_call_recv_message = GetMethodDelegate<Delegates.grpcsharp_call_recv_message_delegate>(library); - this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_recv_initial_metadata_delegate>(library); - this.grpcsharp_call_start_serverside = GetMethodDelegate<Delegates.grpcsharp_call_start_serverside_delegate>(library); - this.grpcsharp_call_send_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_send_initial_metadata_delegate>(library); - this.grpcsharp_call_set_credentials = GetMethodDelegate<Delegates.grpcsharp_call_set_credentials_delegate>(library); - this.grpcsharp_call_get_peer = GetMethodDelegate<Delegates.grpcsharp_call_get_peer_delegate>(library); - this.grpcsharp_call_destroy = GetMethodDelegate<Delegates.grpcsharp_call_destroy_delegate>(library); - - this.grpcsharp_channel_args_create = GetMethodDelegate<Delegates.grpcsharp_channel_args_create_delegate>(library); - this.grpcsharp_channel_args_set_string = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_string_delegate>(library); - this.grpcsharp_channel_args_set_integer = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_integer_delegate>(library); - this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library); - - this.grpcsharp_override_default_ssl_roots = GetMethodDelegate<Delegates.grpcsharp_override_default_ssl_roots>(library); - this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library); - this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library); - this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library); - - this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library); - this.grpcsharp_secure_channel_create = GetMethodDelegate<Delegates.grpcsharp_secure_channel_create_delegate>(library); - this.grpcsharp_channel_create_call = GetMethodDelegate<Delegates.grpcsharp_channel_create_call_delegate>(library); - this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_check_connectivity_state_delegate>(library); - this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_watch_connectivity_state_delegate>(library); - this.grpcsharp_channel_get_target = GetMethodDelegate<Delegates.grpcsharp_channel_get_target_delegate>(library); - this.grpcsharp_channel_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_destroy_delegate>(library); - - this.grpcsharp_sizeof_grpc_event = GetMethodDelegate<Delegates.grpcsharp_sizeof_grpc_event_delegate>(library); - - this.grpcsharp_completion_queue_create = GetMethodDelegate<Delegates.grpcsharp_completion_queue_create_delegate>(library); - this.grpcsharp_completion_queue_shutdown = GetMethodDelegate<Delegates.grpcsharp_completion_queue_shutdown_delegate>(library); - this.grpcsharp_completion_queue_next = GetMethodDelegate<Delegates.grpcsharp_completion_queue_next_delegate>(library); - this.grpcsharp_completion_queue_pluck = GetMethodDelegate<Delegates.grpcsharp_completion_queue_pluck_delegate>(library); - this.grpcsharp_completion_queue_destroy = GetMethodDelegate<Delegates.grpcsharp_completion_queue_destroy_delegate>(library); - - this.gprsharp_free = GetMethodDelegate<Delegates.gprsharp_free_delegate>(library); - - this.grpcsharp_metadata_array_create = GetMethodDelegate<Delegates.grpcsharp_metadata_array_create_delegate>(library); - this.grpcsharp_metadata_array_add = GetMethodDelegate<Delegates.grpcsharp_metadata_array_add_delegate>(library); - this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library); - this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library); - this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library); - this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library); - this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library); - - this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library); - - this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library); - this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library); - - this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library); - this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library); - - this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library); - this.grpcsharp_server_register_completion_queue = GetMethodDelegate<Delegates.grpcsharp_server_register_completion_queue_delegate>(library); - this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library); - this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library); - this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library); - this.grpcsharp_server_request_call = GetMethodDelegate<Delegates.grpcsharp_server_request_call_delegate>(library); - this.grpcsharp_server_cancel_all_calls = GetMethodDelegate<Delegates.grpcsharp_server_cancel_all_calls_delegate>(library); - this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library); - this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library); - - this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library); - this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library); - this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library); - this.gprsharp_convert_clock_type = GetMethodDelegate<Delegates.gprsharp_convert_clock_type_delegate>(library); - this.gprsharp_sizeof_timespec = GetMethodDelegate<Delegates.gprsharp_sizeof_timespec_delegate>(library); - - this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library); - this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library); - } - else - { - // Windows or fallback - this.grpcsharp_init = PInvokeMethods.grpcsharp_init; - this.grpcsharp_shutdown = PInvokeMethods.grpcsharp_shutdown; - this.grpcsharp_version_string = PInvokeMethods.grpcsharp_version_string; - - this.grpcsharp_batch_context_create = PInvokeMethods.grpcsharp_batch_context_create; - this.grpcsharp_batch_context_recv_initial_metadata = PInvokeMethods.grpcsharp_batch_context_recv_initial_metadata; - this.grpcsharp_batch_context_recv_message_length = PInvokeMethods.grpcsharp_batch_context_recv_message_length; - this.grpcsharp_batch_context_recv_message_to_buffer = PInvokeMethods.grpcsharp_batch_context_recv_message_to_buffer; - this.grpcsharp_batch_context_recv_status_on_client_status = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_status; - this.grpcsharp_batch_context_recv_status_on_client_details = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_details; - this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; - this.grpcsharp_batch_context_server_rpc_new_call = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_call; - this.grpcsharp_batch_context_server_rpc_new_method = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_method; - this.grpcsharp_batch_context_server_rpc_new_host = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_host; - this.grpcsharp_batch_context_server_rpc_new_deadline = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_deadline; - this.grpcsharp_batch_context_server_rpc_new_request_metadata = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_request_metadata; - this.grpcsharp_batch_context_recv_close_on_server_cancelled = PInvokeMethods.grpcsharp_batch_context_recv_close_on_server_cancelled; - this.grpcsharp_batch_context_destroy = PInvokeMethods.grpcsharp_batch_context_destroy; - - this.grpcsharp_composite_call_credentials_create = PInvokeMethods.grpcsharp_composite_call_credentials_create; - this.grpcsharp_call_credentials_release = PInvokeMethods.grpcsharp_call_credentials_release; - - this.grpcsharp_call_cancel = PInvokeMethods.grpcsharp_call_cancel; - this.grpcsharp_call_cancel_with_status = PInvokeMethods.grpcsharp_call_cancel_with_status; - this.grpcsharp_call_start_unary = PInvokeMethods.grpcsharp_call_start_unary; - this.grpcsharp_call_start_client_streaming = PInvokeMethods.grpcsharp_call_start_client_streaming; - this.grpcsharp_call_start_server_streaming = PInvokeMethods.grpcsharp_call_start_server_streaming; - this.grpcsharp_call_start_duplex_streaming = PInvokeMethods.grpcsharp_call_start_duplex_streaming; - this.grpcsharp_call_send_message = PInvokeMethods.grpcsharp_call_send_message; - this.grpcsharp_call_send_close_from_client = PInvokeMethods.grpcsharp_call_send_close_from_client; - this.grpcsharp_call_send_status_from_server = PInvokeMethods.grpcsharp_call_send_status_from_server; - this.grpcsharp_call_recv_message = PInvokeMethods.grpcsharp_call_recv_message; - this.grpcsharp_call_recv_initial_metadata = PInvokeMethods.grpcsharp_call_recv_initial_metadata; - this.grpcsharp_call_start_serverside = PInvokeMethods.grpcsharp_call_start_serverside; - this.grpcsharp_call_send_initial_metadata = PInvokeMethods.grpcsharp_call_send_initial_metadata; - this.grpcsharp_call_set_credentials = PInvokeMethods.grpcsharp_call_set_credentials; - this.grpcsharp_call_get_peer = PInvokeMethods.grpcsharp_call_get_peer; - this.grpcsharp_call_destroy = PInvokeMethods.grpcsharp_call_destroy; - - this.grpcsharp_channel_args_create = PInvokeMethods.grpcsharp_channel_args_create; - this.grpcsharp_channel_args_set_string = PInvokeMethods.grpcsharp_channel_args_set_string; - this.grpcsharp_channel_args_set_integer = PInvokeMethods.grpcsharp_channel_args_set_integer; - this.grpcsharp_channel_args_destroy = PInvokeMethods.grpcsharp_channel_args_destroy; - - this.grpcsharp_override_default_ssl_roots = PInvokeMethods.grpcsharp_override_default_ssl_roots; - this.grpcsharp_ssl_credentials_create = PInvokeMethods.grpcsharp_ssl_credentials_create; - this.grpcsharp_composite_channel_credentials_create = PInvokeMethods.grpcsharp_composite_channel_credentials_create; - this.grpcsharp_channel_credentials_release = PInvokeMethods.grpcsharp_channel_credentials_release; - - this.grpcsharp_insecure_channel_create = PInvokeMethods.grpcsharp_insecure_channel_create; - this.grpcsharp_secure_channel_create = PInvokeMethods.grpcsharp_secure_channel_create; - this.grpcsharp_channel_create_call = PInvokeMethods.grpcsharp_channel_create_call; - this.grpcsharp_channel_check_connectivity_state = PInvokeMethods.grpcsharp_channel_check_connectivity_state; - this.grpcsharp_channel_watch_connectivity_state = PInvokeMethods.grpcsharp_channel_watch_connectivity_state; - this.grpcsharp_channel_get_target = PInvokeMethods.grpcsharp_channel_get_target; - this.grpcsharp_channel_destroy = PInvokeMethods.grpcsharp_channel_destroy; - - this.grpcsharp_sizeof_grpc_event = PInvokeMethods.grpcsharp_sizeof_grpc_event; - - this.grpcsharp_completion_queue_create = PInvokeMethods.grpcsharp_completion_queue_create; - this.grpcsharp_completion_queue_shutdown = PInvokeMethods.grpcsharp_completion_queue_shutdown; - this.grpcsharp_completion_queue_next = PInvokeMethods.grpcsharp_completion_queue_next; - this.grpcsharp_completion_queue_pluck = PInvokeMethods.grpcsharp_completion_queue_pluck; - this.grpcsharp_completion_queue_destroy = PInvokeMethods.grpcsharp_completion_queue_destroy; - - this.gprsharp_free = PInvokeMethods.gprsharp_free; - - this.grpcsharp_metadata_array_create = PInvokeMethods.grpcsharp_metadata_array_create; - this.grpcsharp_metadata_array_add = PInvokeMethods.grpcsharp_metadata_array_add; - this.grpcsharp_metadata_array_count = PInvokeMethods.grpcsharp_metadata_array_count; - this.grpcsharp_metadata_array_get_key = PInvokeMethods.grpcsharp_metadata_array_get_key; - this.grpcsharp_metadata_array_get_value = PInvokeMethods.grpcsharp_metadata_array_get_value; - this.grpcsharp_metadata_array_get_value_length = PInvokeMethods.grpcsharp_metadata_array_get_value_length; - this.grpcsharp_metadata_array_destroy_full = PInvokeMethods.grpcsharp_metadata_array_destroy_full; - - this.grpcsharp_redirect_log = PInvokeMethods.grpcsharp_redirect_log; - - this.grpcsharp_metadata_credentials_create_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_create_from_plugin; - this.grpcsharp_metadata_credentials_notify_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_notify_from_plugin; - - this.grpcsharp_ssl_server_credentials_create = PInvokeMethods.grpcsharp_ssl_server_credentials_create; - this.grpcsharp_server_credentials_release = PInvokeMethods.grpcsharp_server_credentials_release; - - this.grpcsharp_server_create = PInvokeMethods.grpcsharp_server_create; - this.grpcsharp_server_register_completion_queue = PInvokeMethods.grpcsharp_server_register_completion_queue; - this.grpcsharp_server_add_insecure_http2_port = PInvokeMethods.grpcsharp_server_add_insecure_http2_port; - this.grpcsharp_server_add_secure_http2_port = PInvokeMethods.grpcsharp_server_add_secure_http2_port; - this.grpcsharp_server_start = PInvokeMethods.grpcsharp_server_start; - this.grpcsharp_server_request_call = PInvokeMethods.grpcsharp_server_request_call; - this.grpcsharp_server_cancel_all_calls = PInvokeMethods.grpcsharp_server_cancel_all_calls; - this.grpcsharp_server_shutdown_and_notify_callback = PInvokeMethods.grpcsharp_server_shutdown_and_notify_callback; - this.grpcsharp_server_destroy = PInvokeMethods.grpcsharp_server_destroy; - - this.gprsharp_now = PInvokeMethods.gprsharp_now; - this.gprsharp_inf_future = PInvokeMethods.gprsharp_inf_future; - this.gprsharp_inf_past = PInvokeMethods.gprsharp_inf_past; - this.gprsharp_convert_clock_type = PInvokeMethods.gprsharp_convert_clock_type; - this.gprsharp_sizeof_timespec = PInvokeMethods.gprsharp_sizeof_timespec; - - this.grpcsharp_test_callback = PInvokeMethods.grpcsharp_test_callback; - this.grpcsharp_test_nop = PInvokeMethods.grpcsharp_test_nop; - } + this.grpcsharp_init = GetMethodDelegate<Delegates.grpcsharp_init_delegate>(library); + this.grpcsharp_shutdown = GetMethodDelegate<Delegates.grpcsharp_shutdown_delegate>(library); + this.grpcsharp_version_string = GetMethodDelegate<Delegates.grpcsharp_version_string_delegate>(library); + + this.grpcsharp_batch_context_create = GetMethodDelegate<Delegates.grpcsharp_batch_context_create_delegate>(library); + this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate>(library); + this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_length_delegate>(library); + this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library); + this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library); + this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library); + + this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library); + this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library); + + this.grpcsharp_call_cancel = GetMethodDelegate<Delegates.grpcsharp_call_cancel_delegate>(library); + this.grpcsharp_call_cancel_with_status = GetMethodDelegate<Delegates.grpcsharp_call_cancel_with_status_delegate>(library); + this.grpcsharp_call_start_unary = GetMethodDelegate<Delegates.grpcsharp_call_start_unary_delegate>(library); + this.grpcsharp_call_start_client_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_client_streaming_delegate>(library); + this.grpcsharp_call_start_server_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_server_streaming_delegate>(library); + this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_duplex_streaming_delegate>(library); + this.grpcsharp_call_send_message = GetMethodDelegate<Delegates.grpcsharp_call_send_message_delegate>(library); + this.grpcsharp_call_send_close_from_client = GetMethodDelegate<Delegates.grpcsharp_call_send_close_from_client_delegate>(library); + this.grpcsharp_call_send_status_from_server = GetMethodDelegate<Delegates.grpcsharp_call_send_status_from_server_delegate>(library); + this.grpcsharp_call_recv_message = GetMethodDelegate<Delegates.grpcsharp_call_recv_message_delegate>(library); + this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_recv_initial_metadata_delegate>(library); + this.grpcsharp_call_start_serverside = GetMethodDelegate<Delegates.grpcsharp_call_start_serverside_delegate>(library); + this.grpcsharp_call_send_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_send_initial_metadata_delegate>(library); + this.grpcsharp_call_set_credentials = GetMethodDelegate<Delegates.grpcsharp_call_set_credentials_delegate>(library); + this.grpcsharp_call_get_peer = GetMethodDelegate<Delegates.grpcsharp_call_get_peer_delegate>(library); + this.grpcsharp_call_destroy = GetMethodDelegate<Delegates.grpcsharp_call_destroy_delegate>(library); + + this.grpcsharp_channel_args_create = GetMethodDelegate<Delegates.grpcsharp_channel_args_create_delegate>(library); + this.grpcsharp_channel_args_set_string = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_string_delegate>(library); + this.grpcsharp_channel_args_set_integer = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_integer_delegate>(library); + this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library); + + this.grpcsharp_override_default_ssl_roots = GetMethodDelegate<Delegates.grpcsharp_override_default_ssl_roots>(library); + this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library); + this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library); + this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library); + + this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library); + this.grpcsharp_secure_channel_create = GetMethodDelegate<Delegates.grpcsharp_secure_channel_create_delegate>(library); + this.grpcsharp_channel_create_call = GetMethodDelegate<Delegates.grpcsharp_channel_create_call_delegate>(library); + this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_check_connectivity_state_delegate>(library); + this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_watch_connectivity_state_delegate>(library); + this.grpcsharp_channel_get_target = GetMethodDelegate<Delegates.grpcsharp_channel_get_target_delegate>(library); + this.grpcsharp_channel_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_destroy_delegate>(library); + + this.grpcsharp_sizeof_grpc_event = GetMethodDelegate<Delegates.grpcsharp_sizeof_grpc_event_delegate>(library); + + this.grpcsharp_completion_queue_create = GetMethodDelegate<Delegates.grpcsharp_completion_queue_create_delegate>(library); + this.grpcsharp_completion_queue_shutdown = GetMethodDelegate<Delegates.grpcsharp_completion_queue_shutdown_delegate>(library); + this.grpcsharp_completion_queue_next = GetMethodDelegate<Delegates.grpcsharp_completion_queue_next_delegate>(library); + this.grpcsharp_completion_queue_pluck = GetMethodDelegate<Delegates.grpcsharp_completion_queue_pluck_delegate>(library); + this.grpcsharp_completion_queue_destroy = GetMethodDelegate<Delegates.grpcsharp_completion_queue_destroy_delegate>(library); + + this.gprsharp_free = GetMethodDelegate<Delegates.gprsharp_free_delegate>(library); + + this.grpcsharp_metadata_array_create = GetMethodDelegate<Delegates.grpcsharp_metadata_array_create_delegate>(library); + this.grpcsharp_metadata_array_add = GetMethodDelegate<Delegates.grpcsharp_metadata_array_add_delegate>(library); + this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library); + this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library); + this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library); + this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library); + this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library); + + this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library); + + this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library); + this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library); + + this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library); + this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library); + + this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library); + this.grpcsharp_server_register_completion_queue = GetMethodDelegate<Delegates.grpcsharp_server_register_completion_queue_delegate>(library); + this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library); + this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library); + this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library); + this.grpcsharp_server_request_call = GetMethodDelegate<Delegates.grpcsharp_server_request_call_delegate>(library); + this.grpcsharp_server_cancel_all_calls = GetMethodDelegate<Delegates.grpcsharp_server_cancel_all_calls_delegate>(library); + this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library); + this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library); + + this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library); + this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library); + this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library); + this.gprsharp_convert_clock_type = GetMethodDelegate<Delegates.gprsharp_convert_clock_type_delegate>(library); + this.gprsharp_sizeof_timespec = GetMethodDelegate<Delegates.gprsharp_sizeof_timespec_delegate>(library); + + this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library); + this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library); } /// <summary> @@ -516,317 +408,5 @@ namespace Grpc.Core.Internal public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); } - - /// <summary> - /// Default PInvoke bindings for native methods that are used on Windows. - /// Alternatively, they can also be used as a fallback on Mono - /// (if libgrpc_csharp_ext is installed on your system, or is made accessible through e.g. LD_LIBRARY_PATH environment variable - /// or using Mono's dllMap feature). - /// </summary> - private class PInvokeMethods - { - // Environment - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_init(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_shutdown(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_version_string(); // returns not-owned const char* - - // BatchContextSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_batch_context_recv_message_to_buffer(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen); - - [DllImport("grpc_csharp_ext.dll")] - public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx); // returns const char* - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallSafeHandle grpcsharp_batch_context_server_rpc_new_call(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_server_rpc_new_method(BatchContextSafeHandle ctx); // returns const char* - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_server_rpc_new_host(BatchContextSafeHandle ctx); // returns const char* - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec grpcsharp_batch_context_server_rpc_new_deadline(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_server_rpc_new_request_metadata(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); - - // CallCredentialsSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_call_credentials_release(IntPtr credentials); - - // CallSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, - MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, - BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, - byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_call_destroy(IntPtr call); - - // ChannelArgsSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_args_destroy(IntPtr args); - - // ChannelCredentialsSafeHandle - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); - - // ChannelSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, - Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_destroy(IntPtr channel); - - // CompletionQueueEvent - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_sizeof_grpc_event(); - - // CompletionQueueSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); - - // CStringSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern void gprsharp_free(IntPtr ptr); - - // MetadataArraySafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); - - [DllImport("grpc_csharp_ext.dll")] - public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - public static extern UIntPtr grpcsharp_metadata_array_get_value_length(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); - - // NativeLogRedirector - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_redirect_log(GprLogDelegate callback); - - // NativeMetadataCredentialsPlugin - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); - - // ServerCredentialsSafeHandle - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_credentials_release(IntPtr credentials); - - // ServerSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_start(ServerSafeHandle server); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_destroy(IntPtr server); - - // Timespec - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_now(ClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_inf_future(ClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_inf_past(ClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int gprsharp_sizeof_timespec(); - - // Testing - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); - } } } diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs index 5a80746101..dc629bd714 100644 --- a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs +++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs @@ -82,6 +82,32 @@ namespace Grpc.Core.Internal /// <returns></returns> public IntPtr LoadSymbol(string symbolName) { + if (PlatformApis.IsWindows) + { + // See http://stackoverflow.com/questions/10473310 for background on this. + if (PlatformApis.Is64Bit) + { + return Windows.GetProcAddress(this.handle, symbolName); + } + else + { + // Yes, we could potentially predict the size... but it's a lot simpler to just try + // all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying + // many options - and if it takes a little bit longer to fail if we've really got the wrong + // library, that's not a big problem. This is only called once per function in the native library. + symbolName = "_" + symbolName + "@"; + for (int stackSize = 0; stackSize < 128; stackSize += 4) + { + IntPtr candidate = Windows.GetProcAddress(this.handle, symbolName + stackSize); + if (candidate != IntPtr.Zero) + { + return candidate; + } + } + // Fail. + return IntPtr.Zero; + } + } if (PlatformApis.IsLinux) { if (PlatformApis.IsMono) @@ -142,13 +168,18 @@ namespace Grpc.Core.Internal return path; } } - throw new FileNotFoundException(String.Format("Error loading native library. Not found in any of the possible locations {0}", libraryPathAlternatives)); + throw new FileNotFoundException( + String.Format("Error loading native library. Not found in any of the possible locations: {0}", + string.Join(",", libraryPathAlternatives))); } private static class Windows { [DllImport("kernel32.dll")] internal static extern IntPtr LoadLibrary(string filename); + + [DllImport("kernel32.dll")] + internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); } private static class Linux diff --git a/src/csharp/Grpc.Core/NativeDeps.Linux.targets b/src/csharp/Grpc.Core/NativeDeps.Linux.targets index a3848c6f2e..e0c9132b1d 100644 --- a/src/csharp/Grpc.Core/NativeDeps.Linux.targets +++ b/src/csharp/Grpc.Core/NativeDeps.Linux.targets @@ -3,7 +3,7 @@ <ItemGroup> <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link> + <Link>libgrpc_csharp_ext.x64.so</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/NativeDeps.Mac.targets b/src/csharp/Grpc.Core/NativeDeps.Mac.targets index c3c6264fd3..e22c7384fc 100644 --- a/src/csharp/Grpc.Core/NativeDeps.Mac.targets +++ b/src/csharp/Grpc.Core/NativeDeps.Mac.targets @@ -3,7 +3,7 @@ <ItemGroup> <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link> + <Link>libgrpc_csharp_ext.x86.dylib</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/NativeDeps.Windows.targets b/src/csharp/Grpc.Core/NativeDeps.Windows.targets index f6a3405e29..93db0935bc 100644 --- a/src/csharp/Grpc.Core/NativeDeps.Windows.targets +++ b/src/csharp/Grpc.Core/NativeDeps.Windows.targets @@ -3,7 +3,7 @@ <ItemGroup> <Content Include="..\..\..\vsprojects\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link> + <Link>grpc_csharp_ext.x86.dll</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index cb20967680..e9f5c63372 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -48,11 +48,11 @@ namespace Grpc.Core /// <summary> /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies /// </summary> - public const string CurrentAssemblyFileVersion = "0.16.0.0"; + public const string CurrentAssemblyFileVersion = "1.0.0.0"; /// <summary> /// Current version of gRPC C# /// </summary> - public const string CurrentVersion = "0.16.0-dev"; + public const string CurrentVersion = "1.0.0-pre1"; } } diff --git a/src/csharp/Grpc.Core/project.json b/src/csharp/Grpc.Core/project.json index 201e548801..7a676f59a6 100644 --- a/src/csharp/Grpc.Core/project.json +++ b/src/csharp/Grpc.Core/project.json @@ -1,5 +1,5 @@ { - "version": "0.16.0-dev", + "version": "1.0.0-pre1", "title": "gRPC C# Core", "authors": [ "Google Inc." ], "copyright": "Copyright 2015, Google Inc.", @@ -14,12 +14,12 @@ "files": { "mappings": { "build/net45/": "Grpc.Core.targets", - "build/native/bin/windows_x86/": "../nativelibs/windows_x86/grpc_csharp_ext.dll", - "build/native/bin/windows_x64/": "../nativelibs/windows_x64/grpc_csharp_ext.dll", - "build/native/bin/linux_x86/": "../nativelibs/linux_x86/libgrpc_csharp_ext.so", - "build/native/bin/linux_x64/": "../nativelibs/linux_x64/libgrpc_csharp_ext.so", - "build/native/bin/macosx_x86/": "../nativelibs/macosx_x86/libgrpc_csharp_ext.dylib", - "build/native/bin/macosx_x64/": "../nativelibs/macosx_x64/libgrpc_csharp_ext.dylib" + "runtimes/win/native/grpc_csharp_ext.x86.dll": "../nativelibs/windows_x86/grpc_csharp_ext.dll", + "runtimes/win/native/grpc_csharp_ext.x64.dll": "../nativelibs/windows_x64/grpc_csharp_ext.dll", + "runtimes/linux/native/libgrpc_csharp_ext.x86.so": "../nativelibs/linux_x86/libgrpc_csharp_ext.so", + "runtimes/linux/native/libgrpc_csharp_ext.x64.so": "../nativelibs/linux_x64/libgrpc_csharp_ext.so", + "runtimes/osx/native/libgrpc_csharp_ext.x86.dylib": "../nativelibs/macosx_x86/libgrpc_csharp_ext.dylib", + "runtimes/osx/native/libgrpc_csharp_ext.x64.dylib": "../nativelibs/macosx_x64/libgrpc_csharp_ext.dylib" } } }, diff --git a/src/csharp/Grpc.Examples.MathClient/project.json b/src/csharp/Grpc.Examples.MathClient/project.json index b865cd5011..206d6c5982 100644 --- a/src/csharp/Grpc.Examples.MathClient/project.json +++ b/src/csharp/Grpc.Examples.MathClient/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.Examples.MathServer/project.json b/src/csharp/Grpc.Examples.MathServer/project.json index b865cd5011..206d6c5982 100644 --- a/src/csharp/Grpc.Examples.MathServer/project.json +++ b/src/csharp/Grpc.Examples.MathServer/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.Examples.Tests/project.json b/src/csharp/Grpc.Examples.Tests/project.json index cc518eb6ff..b4c4c5f691 100644 --- a/src/csharp/Grpc.Examples.Tests/project.json +++ b/src/csharp/Grpc.Examples.Tests/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.HealthCheck.Tests/project.json b/src/csharp/Grpc.HealthCheck.Tests/project.json index fbf8d92f04..f44a3225ae 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/project.json +++ b/src/csharp/Grpc.HealthCheck.Tests/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json index d9daef720f..906dda3624 100644 --- a/src/csharp/Grpc.HealthCheck/project.json +++ b/src/csharp/Grpc.HealthCheck/project.json @@ -1,5 +1,5 @@ { - "version": "0.16.0-dev", + "version": "1.0.0-pre1", "title": "gRPC C# Healthchecking", "authors": [ "Google Inc." ], "copyright": "Copyright 2015, Google Inc.", @@ -22,7 +22,7 @@ } }, "dependencies": { - "Grpc.Core": "0.16.0-dev", + "Grpc.Core": "1.0.0-pre1", "Google.Protobuf": "3.0.0-beta3" }, "frameworks": { diff --git a/src/csharp/Grpc.IntegrationTesting.Client/project.json b/src/csharp/Grpc.IntegrationTesting.Client/project.json index 4a2846feea..6b61a4b76e 100644 --- a/src/csharp/Grpc.IntegrationTesting.Client/project.json +++ b/src/csharp/Grpc.IntegrationTesting.Client/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json index 4a2846feea..6b61a4b76e 100644 --- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json +++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.IntegrationTesting.Server/project.json b/src/csharp/Grpc.IntegrationTesting.Server/project.json index 4a2846feea..6b61a4b76e 100644 --- a/src/csharp/Grpc.IntegrationTesting.Server/project.json +++ b/src/csharp/Grpc.IntegrationTesting.Server/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json index 4a2846feea..6b61a4b76e 100644 --- a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json +++ b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/Grpc.IntegrationTesting/project.json b/src/csharp/Grpc.IntegrationTesting/project.json index 6297600ddc..dcd9ccabd2 100644 --- a/src/csharp/Grpc.IntegrationTesting/project.json +++ b/src/csharp/Grpc.IntegrationTesting/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } diff --git a/src/csharp/README.md b/src/csharp/README.md index 86394135c8..18d5945a8a 100644 --- a/src/csharp/README.md +++ b/src/csharp/README.md @@ -23,9 +23,9 @@ HOW TO USE - Open Visual Studio / MonoDevelop / Xamarin Studio and start a new project/solution. -- Add NuGet package `Grpc` as a dependency (Project options -> Manage NuGet Packages). +- Add the [Grpc](https://www.nuget.org/packages/Grpc/) NuGet package as a dependency (Project options -> Manage NuGet Packages). -- To be able to generate code from Protocol Buffer (`.proto`) file definitions, add NuGet package `Grpc.Tools` that contains Protocol Buffers compiler (_protoc_) and the gRPC _protoc_ plugin. +- To be able to generate code from Protocol Buffer (`.proto`) file definitions, add the [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools/) NuGet package that contains Protocol Buffers compiler (_protoc_) and the gRPC _protoc_ plugin. BUILD FROM SOURCE ----------------- diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 272b30f385..ffb70addad 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -30,7 +30,7 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.16.0-dev +set VERSION=1.0.0-pre1 set PROTOBUF_VERSION=3.0.0-beta3 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well. diff --git a/src/node/health_check/LICENSE b/src/node/health_check/LICENSE new file mode 100644 index 0000000000..0209b570e1 --- /dev/null +++ b/src/node/health_check/LICENSE @@ -0,0 +1,28 @@ +Copyright 2015, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/node/health_check/health.js b/src/node/health_check/health.js index 5236683088..64ba9fb960 100644 --- a/src/node/health_check/health.js +++ b/src/node/health_check/health.js @@ -33,14 +33,12 @@ 'use strict'; -var grpc = require('../'); +var grpc = require('grpc'); var _ = require('lodash'); -var health_proto = grpc.load(__dirname + - '/../../proto/grpc/health/v1/health.proto'); - -var HealthClient = health_proto.grpc.health.v1.Health; +var health_messages = require('./v1/health_pb'); +var health_service = require('./v1/health_grpc_pb'); function HealthImplementation(statusMap) { this.statusMap = _.clone(statusMap); @@ -51,17 +49,19 @@ HealthImplementation.prototype.setStatus = function(service, status) { }; HealthImplementation.prototype.check = function(call, callback){ - var service = call.request.service; + var service = call.request.getService(); var status = _.get(this.statusMap, service, null); if (status === null) { callback({code:grpc.status.NOT_FOUND}); } else { - callback(null, {status: status}); + var response = new health_messages.HealthCheckResponse(); + response.setStatus(status); + callback(null, response); } }; module.exports = { - Client: HealthClient, - service: HealthClient.service, + Client: health_service.HealthClient, + service: health_service.HealthService, Implementation: HealthImplementation }; diff --git a/src/objective-c/examples/SwiftSample/Bridging-Header.h b/src/node/health_check/node_modules/grpc.js index 65f768a760..42161198cc 100644 --- a/src/objective-c/examples/SwiftSample/Bridging-Header.h +++ b/src/node/health_check/node_modules/grpc.js @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,15 +31,7 @@ * */ -#ifndef SwiftSample_Bridging_Header_h -#define SwiftSample_Bridging_Header_h +/* This exists solely to allow the generated code to import the grpc module + * without using a relative path */ -#import <RxLibrary/GRXWriteable.h> -#import <RxLibrary/GRXWriter.h> -#import <RxLibrary/GRXWriter+Immediate.h> -#import <GRPCClient/GRPCCall.h> -#import <ProtoRPC/ProtoMethod.h> -#import <ProtoRPC/ProtoRPC.h> -#import <RemoteTest/Test.pbrpc.h> - -#endif +module.exports = require('../..'); diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json new file mode 100644 index 0000000000..b68e8b1a80 --- /dev/null +++ b/src/node/health_check/package.json @@ -0,0 +1,29 @@ +{ + "name": "grpc-health-check", + "version": "1.0.0-pre1", + "author": "Google Inc.", + "description": "Health check service for use with gRPC", + "repository": { + "type": "git", + "url": "https://github.com/grpc/grpc.git" + }, + "bugs": "https://github.com/grpc/grpc/issues", + "contributors": [ + { + "name": "Michael Lumish", + "email": "mlumish@google.com" + } + ], + "dependencies": { + "grpc": "^0.15.0", + "lodash": "^3.9.3", + "google-protobuf": "^3.0.0-alpha.5" + }, + "files": { + "LICENSE", + "health.js", + "v1" + }, + "main": "src/node/index.js", + "license": "BSD-3-Clause" +} diff --git a/src/objective-c/examples/RemoteTestClient/empty.proto b/src/node/health_check/v1/health_grpc_pb.js index a678048289..89bc304e56 100644 --- a/src/objective-c/examples/RemoteTestClient/empty.proto +++ b/src/node/health_check/v1/health_grpc_pb.js @@ -1,3 +1,6 @@ +// GENERATED CODE -- DO NOT EDIT! + +// Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // @@ -26,19 +29,46 @@ // 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. +// +'use strict'; +var grpc = require('grpc'); +var v1_health_pb = require('../v1/health_pb.js'); -syntax = "proto3"; +function serialize_HealthCheckRequest(arg) { + if (!(arg instanceof v1_health_pb.HealthCheckRequest)) { + throw new Error('Expected argument of type HealthCheckRequest'); + } + return new Buffer(arg.serializeBinary()); +} -package grpc.testing; +function deserialize_HealthCheckRequest(buffer_arg) { + return v1_health_pb.HealthCheckRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} -option objc_class_prefix = "RMT"; +function serialize_HealthCheckResponse(arg) { + if (!(arg instanceof v1_health_pb.HealthCheckResponse)) { + throw new Error('Expected argument of type HealthCheckResponse'); + } + return new Buffer(arg.serializeBinary()); +} -// An empty message that you can re-use to avoid defining duplicated empty -// messages in your project. A typical example is to use it as argument or the -// return value of a service API. For instance: -// -// service Foo { -// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; -// }; -// -message Empty {} +function deserialize_HealthCheckResponse(buffer_arg) { + return v1_health_pb.HealthCheckResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + + +var HealthService = exports.HealthService = { + check: { + path: '/grpc.health.v1.Health/Check', + requestStream: false, + responseStream: false, + requestType: v1_health_pb.HealthCheckRequest, + responseType: v1_health_pb.HealthCheckResponse, + requestSerialize: serialize_HealthCheckRequest, + requestDeserialize: deserialize_HealthCheckRequest, + responseSerialize: serialize_HealthCheckResponse, + responseDeserialize: deserialize_HealthCheckResponse, + }, +}; + +exports.HealthClient = grpc.makeGenericClientConstructor(HealthService); diff --git a/src/node/health_check/v1/health_pb.js b/src/node/health_check/v1/health_pb.js new file mode 100644 index 0000000000..b36d47cdbb --- /dev/null +++ b/src/node/health_check/v1/health_pb.js @@ -0,0 +1,342 @@ +/** + * @fileoverview + * @enhanceable + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +goog.exportSymbol('proto.grpc.health.v1.HealthCheckRequest', null, global); +goog.exportSymbol('proto.grpc.health.v1.HealthCheckResponse', null, global); +goog.exportSymbol('proto.grpc.health.v1.HealthCheckResponse.ServingStatus', null, global); + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.grpc.health.v1.HealthCheckRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.grpc.health.v1.HealthCheckRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.grpc.health.v1.HealthCheckRequest.displayName = 'proto.grpc.health.v1.HealthCheckRequest'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.grpc.health.v1.HealthCheckRequest.prototype.toObject = function(opt_includeInstance) { + return proto.grpc.health.v1.HealthCheckRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.grpc.health.v1.HealthCheckRequest} msg The msg instance to transform. + * @return {!Object} + */ +proto.grpc.health.v1.HealthCheckRequest.toObject = function(includeInstance, msg) { + var f, obj = { + service: msg.getService() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.grpc.health.v1.HealthCheckRequest} + */ +proto.grpc.health.v1.HealthCheckRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.grpc.health.v1.HealthCheckRequest; + return proto.grpc.health.v1.HealthCheckRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.grpc.health.v1.HealthCheckRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.grpc.health.v1.HealthCheckRequest} + */ +proto.grpc.health.v1.HealthCheckRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setService(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Class method variant: serializes the given message to binary data + * (in protobuf wire format), writing to the given BinaryWriter. + * @param {!proto.grpc.health.v1.HealthCheckRequest} message + * @param {!jspb.BinaryWriter} writer + */ +proto.grpc.health.v1.HealthCheckRequest.serializeBinaryToWriter = function(message, writer) { + message.serializeBinaryToWriter(writer); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.grpc.health.v1.HealthCheckRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + this.serializeBinaryToWriter(writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format), + * writing to the given BinaryWriter. + * @param {!jspb.BinaryWriter} writer + */ +proto.grpc.health.v1.HealthCheckRequest.prototype.serializeBinaryToWriter = function (writer) { + var f = undefined; + f = this.getService(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * Creates a deep clone of this proto. No data is shared with the original. + * @return {!proto.grpc.health.v1.HealthCheckRequest} The clone. + */ +proto.grpc.health.v1.HealthCheckRequest.prototype.cloneMessage = function() { + return /** @type {!proto.grpc.health.v1.HealthCheckRequest} */ (jspb.Message.cloneMessage(this)); +}; + + +/** + * optional string service = 1; + * @return {string} + */ +proto.grpc.health.v1.HealthCheckRequest.prototype.getService = function() { + return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, "")); +}; + + +/** @param {string} value */ +proto.grpc.health.v1.HealthCheckRequest.prototype.setService = function(value) { + jspb.Message.setField(this, 1, value); +}; + + + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.grpc.health.v1.HealthCheckResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.grpc.health.v1.HealthCheckResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.grpc.health.v1.HealthCheckResponse.displayName = 'proto.grpc.health.v1.HealthCheckResponse'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.grpc.health.v1.HealthCheckResponse.prototype.toObject = function(opt_includeInstance) { + return proto.grpc.health.v1.HealthCheckResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.grpc.health.v1.HealthCheckResponse} msg The msg instance to transform. + * @return {!Object} + */ +proto.grpc.health.v1.HealthCheckResponse.toObject = function(includeInstance, msg) { + var f, obj = { + status: msg.getStatus() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.grpc.health.v1.HealthCheckResponse} + */ +proto.grpc.health.v1.HealthCheckResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.grpc.health.v1.HealthCheckResponse; + return proto.grpc.health.v1.HealthCheckResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.grpc.health.v1.HealthCheckResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.grpc.health.v1.HealthCheckResponse} + */ +proto.grpc.health.v1.HealthCheckResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} */ (reader.readEnum()); + msg.setStatus(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Class method variant: serializes the given message to binary data + * (in protobuf wire format), writing to the given BinaryWriter. + * @param {!proto.grpc.health.v1.HealthCheckResponse} message + * @param {!jspb.BinaryWriter} writer + */ +proto.grpc.health.v1.HealthCheckResponse.serializeBinaryToWriter = function(message, writer) { + message.serializeBinaryToWriter(writer); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.grpc.health.v1.HealthCheckResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + this.serializeBinaryToWriter(writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format), + * writing to the given BinaryWriter. + * @param {!jspb.BinaryWriter} writer + */ +proto.grpc.health.v1.HealthCheckResponse.prototype.serializeBinaryToWriter = function (writer) { + var f = undefined; + f = this.getStatus(); + if (f !== 0.0) { + writer.writeEnum( + 1, + f + ); + } +}; + + +/** + * Creates a deep clone of this proto. No data is shared with the original. + * @return {!proto.grpc.health.v1.HealthCheckResponse} The clone. + */ +proto.grpc.health.v1.HealthCheckResponse.prototype.cloneMessage = function() { + return /** @type {!proto.grpc.health.v1.HealthCheckResponse} */ (jspb.Message.cloneMessage(this)); +}; + + +/** + * optional ServingStatus status = 1; + * @return {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} + */ +proto.grpc.health.v1.HealthCheckResponse.prototype.getStatus = function() { + return /** @type {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} */ (jspb.Message.getFieldProto3(this, 1, 0)); +}; + + +/** @param {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} value */ +proto.grpc.health.v1.HealthCheckResponse.prototype.setStatus = function(value) { + jspb.Message.setField(this, 1, value); +}; + + +/** + * @enum {number} + */ +proto.grpc.health.v1.HealthCheckResponse.ServingStatus = { + UNKNOWN: 0, + SERVING: 1, + NOT_SERVING: 2 +}; + +goog.object.extend(exports, proto.grpc.health.v1); diff --git a/src/node/test/health_test.js b/src/node/test/health_test.js index c93b528d42..efbca46c2d 100644 --- a/src/node/test/health_test.js +++ b/src/node/test/health_test.js @@ -35,15 +35,19 @@ var assert = require('assert'); -var health = require('../health_check/health.js'); +var health = require('../health_check/health'); + +var health_messages = require('../health_check/v1/health_pb'); + +var ServingStatus = health_messages.HealthCheckResponse.ServingStatus; var grpc = require('../'); describe('Health Checking', function() { var statusMap = { - '': 'SERVING', - 'grpc.test.TestServiceNotServing': 'NOT_SERVING', - 'grpc.test.TestServiceServing': 'SERVING' + '': ServingStatus.SERVING, + 'grpc.test.TestServiceNotServing': ServingStatus.NOT_SERVING, + 'grpc.test.TestServiceServing': ServingStatus.SERVING }; var healthServer; var healthImpl; @@ -51,7 +55,7 @@ describe('Health Checking', function() { before(function() { healthServer = new grpc.Server(); healthImpl = new health.Implementation(statusMap); - healthServer.addProtoService(health.service, healthImpl); + healthServer.addService(health.service, healthImpl); var port_num = healthServer.bind('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); healthServer.start(); @@ -62,43 +66,51 @@ describe('Health Checking', function() { healthServer.forceShutdown(); }); it('should say an enabled service is SERVING', function(done) { - healthClient.check({service: ''}, function(err, response) { + var request = new health_messages.HealthCheckRequest(); + request.setService(''); + healthClient.check(request, function(err, response) { assert.ifError(err); - assert.strictEqual(response.status, 'SERVING'); + assert.strictEqual(response.getStatus(), ServingStatus.SERVING); done(); }); }); it('should say that a disabled service is NOT_SERVING', function(done) { - healthClient.check({service: 'grpc.test.TestServiceNotServing'}, - function(err, response) { - assert.ifError(err); - assert.strictEqual(response.status, 'NOT_SERVING'); - done(); - }); + var request = new health_messages.HealthCheckRequest(); + request.setService('grpc.test.TestServiceNotServing'); + healthClient.check(request, function(err, response) { + assert.ifError(err); + assert.strictEqual(response.getStatus(), ServingStatus.NOT_SERVING); + done(); + }); }); it('should say that an enabled service is SERVING', function(done) { - healthClient.check({service: 'grpc.test.TestServiceServing'}, - function(err, response) { - assert.ifError(err); - assert.strictEqual(response.status, 'SERVING'); - done(); - }); + var request = new health_messages.HealthCheckRequest(); + request.setService('grpc.test.TestServiceServing'); + healthClient.check(request, function(err, response) { + assert.ifError(err); + assert.strictEqual(response.getStatus(), ServingStatus.SERVING); + done(); + }); }); it('should get NOT_FOUND if the service is not registered', function(done) { - healthClient.check({service: 'not_registered'}, function(err, response) { + var request = new health_messages.HealthCheckRequest(); + request.setService('not_registered'); + healthClient.check(request, function(err, response) { assert(err); assert.strictEqual(err.code, grpc.status.NOT_FOUND); done(); }); }); it('should get a different response if the status changes', function(done) { - healthClient.check({service: 'transient'}, function(err, response) { + var request = new health_messages.HealthCheckRequest(); + request.setService('transient'); + healthClient.check(request, function(err, response) { assert(err); assert.strictEqual(err.code, grpc.status.NOT_FOUND); - healthImpl.setStatus('transient', 'SERVING'); - healthClient.check({service: 'transient'}, function(err, response) { + healthImpl.setStatus('transient', ServingStatus.SERVING); + healthClient.check(request, function(err, response) { assert.ifError(err); - assert.strictEqual(response.status, 'SERVING'); + assert.strictEqual(response.getStatus(), ServingStatus.SERVING); done(); }); }); diff --git a/src/node/tools/package.json b/src/node/tools/package.json index 7c256d7ba0..7efa0d3f40 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "0.16.0-dev", + "version": "1.0.0-pre1", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec new file mode 100644 index 0000000000..97f4f586b7 --- /dev/null +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -0,0 +1,122 @@ +# CocoaPods podspec for the gRPC Proto Compiler Plugin + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Pod::Spec.new do |s| + # This pod is only a utility that will be used by other pods _at install time_ (not at compile + # time). Other pods can access it in their `prepare_command` script, under <pods_root>/<pod name>. + # Because CocoaPods installs pods in alphabetical order, beginning this pod's name with an + # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed + # before them. + s.name = '!ProtoCompiler-gRPCPlugin' + v = '1.0.0-pre1' + s.version = v + s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' + s.description = <<-DESC + This podspec only downloads the gRPC protoc plugin so that local pods generating protos can use + it in their invocation of protoc, as part of their prepare_command. + The generated code will have a dependency on the gRPC Objective-C Proto runtime of the same + version. The runtime can be obtained as the "gRPC-ProtoRPC" pod. + DESC + s.homepage = 'http://www.grpc.io' + s.license = { + :type => 'New BSD', + :text => <<-LICENSE + Copyright 2015, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + LICENSE + } + s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } + + repo = 'grpc/grpc' + release = "objective-c-v#{v}" + file = "grpc_objective_c_plugin-#{v}-macos-x86_64.zip" + s.source = { + :http => "https://github.com/#{repo}/releases/download/#{release}/#{file}", + # TODO(jcanizales): Add sha1 or sha256 + # :sha1 => '??', + } + + repo_root = '../..' + plugin = 'grpc_objective_c_plugin' + + s.preserve_paths = plugin + + # Restrict the protoc version to the one supported by this plugin. + s.dependency '!ProtoCompiler', '3.0.0-beta-3.1' + # For the Protobuf dependency not to complain: + s.ios.deployment_target = '7.1' + s.osx.deployment_target = '10.9' + # Restrict the gRPC runtime version to the one supported by this plugin. + s.dependency 'gRPC-ProtoRPC', v + + # This is only for local development of the plugin: If the Podfile brings this pod from a local + # directory using `:path`, CocoaPods won't download the zip file and so the plugin won't be + # present in this pod's directory. We use that knowledge to check for the existence of the file + # and, if absent, compile the plugin from the local sources. + s.prepare_command = <<-CMD + if [ ! -f #{plugin} ]; then + cd #{repo_root} + # This will build the plugin and put it in #{repo_root}/bins/opt. + # + # TODO(jcanizales): I reckon make will try to use locally-installed libprotoc (headers and + # library binary) if found, which _we do not want_. Find a way for this to always use the + # sources in the repo. + make #{plugin} + cd - + fi + CMD +end diff --git a/src/objective-c/!ProtoCompiler.podspec b/src/objective-c/!ProtoCompiler.podspec new file mode 100644 index 0000000000..56aacc3330 --- /dev/null +++ b/src/objective-c/!ProtoCompiler.podspec @@ -0,0 +1,135 @@ +# Proto Compiler CocoaPods podspec + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Pod::Spec.new do |s| + # This pod is only a utility that will be used by other pods _at install time_ (not at compile + # time). Other pods can access it in their `prepare_command` script, under <pods_root>/<pod name>. + # Because CocoaPods installs pods in alphabetical order, beginning this pod's name with an + # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed + # before them. + s.name = '!ProtoCompiler' + v = '3.0.0-beta-3.1' + s.version = v + s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files' + s.description = <<-DESC + This podspec only downloads protoc so that local pods generating protos can execute it as part + of their prepare_command. + The generated code will have a dependency on the Protobuf Objective-C runtime of the same + version. The runtime can be obtained as the "Protobuf" pod. + DESC + s.homepage = 'https://github.com/google/protobuf' + s.license = { + :type => 'New BSD', + :text => <<-LICENSE + This license applies to all parts of Protocol Buffers except the following: + + - Atomicops support for generic gcc, located in + src/google/protobuf/stubs/atomicops_internals_generic_gcc.h. + This file is copyrighted by Red Hat Inc. + + - Atomicops support for AIX/POWER, located in + src/google/protobuf/stubs/atomicops_internals_power.h. + This file is copyrighted by Bloomberg Finance LP. + + 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. + + Code generated by the Protocol Buffer compiler is owned by the owner + of the input file used when generating it. This code is not + standalone and requires a support library to be linked with it. This + support library is itself covered by the above license. + LICENSE + } + # "The name and email addresses of the library maintainers, not the Podspec maintainer." + s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' } + + repo = 'google/protobuf' + file = "protoc-#{v}-osx-x86_64.zip" + s.source = { + :http => "https://github.com/#{repo}/releases/download/v#{v}/#{file}", + # TODO(jcanizales): Add sha1 or sha256 + # :sha1 => '??', + } + + s.preserve_paths = 'protoc', + 'google/**/*.proto' # Well-known protobuf types + + # Restrict the protobuf runtime version to the one supported by this version of protoc. + s.dependency 'Protobuf', v + # For the Protobuf dependency not to complain: + s.ios.deployment_target = '7.1' + s.osx.deployment_target = '10.9' + + # This is only for local development of protoc: If the Podfile brings this pod from a local + # directory using `:path`, CocoaPods won't download the zip file and so the compiler won't be + # present in this pod's directory. We use that knowledge to check for the existence of the file + # and, if absent, build it from the local sources. + repo_root = '../..' + plugin = 'grpc_objective_c_plugin' + s.prepare_command = <<-CMD + if [ ! -f protoc ]; then + cd #{repo_root} + # This will build protoc from the Protobuf submodule of gRPC, and put it in + # #{repo_root}/bins/opt/protobuf. + # + # TODO(jcanizales): Make won't build protoc from sources if one's locally installed, which + # _we do not want_. Find a way for this to always build from source. + make #{plugin} + cd - + fi + CMD + +end diff --git a/src/objective-c/BoringSSL.podspec b/src/objective-c/BoringSSL.podspec index 7d1de80716..b759997c11 100644 --- a/src/objective-c/BoringSSL.podspec +++ b/src/objective-c/BoringSSL.podspec @@ -31,7 +31,8 @@ Pod::Spec.new do |s| s.name = 'BoringSSL' - s.version = '3.0' + version = '5.0' + s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.' # Adapted from the homepage: s.description = <<-DESC @@ -66,32 +67,143 @@ Pod::Spec.new do |s| # "The name and email addresses of the library maintainers, not the Podspec maintainer." s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' - s.source = { :git => 'https://boringssl.googlesource.com/boringssl', - :tag => 'version_for_cocoapods_3.0' } + s.source = { + :git => 'https://boringssl.googlesource.com/boringssl', + :tag => "version_for_cocoapods_#{version}", + # :commit => '8d343b44bbab829d1a28fdef650ca95f7db4412e', + } - s.source_files = 'ssl/*.{h,c}', - 'ssl/**/*.{h,c}', - '*.{h,c}', - 'crypto/*.{h,c}', - 'crypto/**/*.{h,c}', - 'include/openssl/*.h' + name = 'openssl' - s.public_header_files = 'include/openssl/*.h' - s.header_mappings_dir = 'include' + # When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework. + # This lets users write their includes like `#include <openssl/ssl.h>` as opposed to `#include + # <BoringSSL/ssl.h>`. + s.module_name = name - s.exclude_files = "**/*_test.*" + # When creating a dynamic framework, copy the headers under `include/openssl/` into the root of + # the `Headers/` directory of the framework (i.e., not under `Headers/include/openssl`). + # + # TODO(jcanizales): Debug why this doesn't work on macOS. + s.header_mappings_dir = 'include/openssl' + + # The above has an undesired effect when creating a static library: It forces users to write + # includes like `#include <BoringSSL/ssl.h>`. `s.header_dir` adds a path prefix to that, and + # because Cocoapods lets omit the pod name when including headers of static libraries, the + # following lets users write `#include <openssl/ssl.h>`. + s.header_dir = name + + # The module map and umbrella header created automatically by Cocoapods don't work for C libraries + # like this one. The following file, and a correct umbrella header, are created on the fly by the + # `prepare_command` of this pod. + s.module_map = 'include/openssl/module.modulemap' # We don't need to inhibit all warnings; only -Wno-shorten-64-to-32. But Cocoapods' linter doesn't # want that for some reason. s.compiler_flags = '-DOPENSSL_NO_ASM', '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' s.requires_arc = false + # Like many other C libraries, BoringSSL has its public headers under `include/<libname>/` and its + # sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't + # allow any header to be listed outside the `header_mappings_dir` (even though doing so works in + # practice). Because we need our `header_mappings_dir` to be `include/openssl/` for the reason + # mentioned above, we work around the linter limitation by dividing the pod into two subspecs, one + # for public headers and the other for implementation. Each gets its own `header_mappings_dir`, + # making the linter happy. + s.subspec 'Interface' do |ss| + ss.header_mappings_dir = 'include/openssl' + ss.source_files = 'include/openssl/*.h' + end + s.subspec 'Implementation' do |ss| + ss.header_mappings_dir = '.' + ss.source_files = 'ssl/*.{h,c}', + 'ssl/**/*.{h,c}', + '*.{h,c}', + 'crypto/*.{h,c}', + 'crypto/**/*.{h,c}' + ss.private_header_files = 'ssl/*.h', + 'ssl/**/*.h', + '*.h', + 'crypto/*.h', + 'crypto/**/*.h' + ss.exclude_files = '**/*_test.*', + '**/test_*.*', + '**/test/*.*' + + ss.dependency "#{s.name}/Interface", version + end + s.prepare_command = <<-END_OF_COMMAND # Replace "const BIGNUM *I" in rsa.h with a lowercase i, as the former fails when including # OpenSSL in a Swift bridging header (complex.h defines "I", and it's as if the compiler # included it in every bridged header). sed -E -i '.back' 's/\\*I,/*i,/g' include/openssl/rsa.h + # Replace `#include "../crypto/internal.h"` in e_tls.c with `#include "../internal.h"`. The + # former assumes crypto/ is in the headers search path, which is hard to enforce when using + # dynamic frameworks. The latters always works, being relative to the current file. + sed -E -i '.back' 's/crypto\\///g' crypto/cipher/e_tls.c + + # Add a module map and an umbrella header + cat > include/openssl/umbrella.h <<EOF + #include "ssl.h" + #include "crypto.h" + #include "aes.h" + /* The following macros are defined by base.h. The latter is the first file included by the + other headers. */ + #if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) + # include "arm_arch.h" + #endif + #include "asn1.h" + #include "asn1_mac.h" + #include "asn1t.h" + #include "blowfish.h" + #include "cast.h" + #include "chacha.h" + #include "cmac.h" + #include "conf.h" + #include "cpu.h" + #include "curve25519.h" + #include "des.h" + #include "dtls1.h" + #include "hkdf.h" + #include "md4.h" + #include "md5.h" + #include "newhope.h" + #include "obj_mac.h" + #include "objects.h" + #include "opensslv.h" + #include "ossl_typ.h" + #include "pkcs12.h" + #include "pkcs7.h" + #include "pkcs8.h" + #include "poly1305.h" + #include "rand.h" + #include "rc4.h" + #include "ripemd.h" + #include "safestack.h" + #include "srtp.h" + #include "time_support.h" + #include "x509.h" + #include "x509v3.h" + EOF + cat > include/openssl/module.modulemap <<EOF + framework module openssl { + umbrella header "umbrella.h" + export * + module * { export * } + } + EOF + + # #include <inttypes.h> fails to compile when building a dynamic framework. libgit2 in + # https://github.com/libgit2/libgit2/commit/1ddada422caf8e72ba97dca2568d2bf879fed5f2 and libvpx + # in https://chromium.googlesource.com/webm/libvpx/+/1bec0c5a7e885ec792f6bb658eb3f34ad8f37b15 + # work around it by removing the include. We need four of its macros, so we expand them here. + sed -E -i '.back' '/<inttypes.h>/d' include/openssl/bn.h + sed -E -i '.back' 's/PRIu32/"u"/g' include/openssl/bn.h + sed -E -i '.back' 's/PRIx32/"x"/g' include/openssl/bn.h + sed -E -i '.back' 's/PRIu64/"llu"/g' include/openssl/bn.h + sed -E -i '.back' 's/PRIx64/"llx"/g' include/openssl/bn.h + # This is a bit ridiculous, but requiring people to install Go in order to build is slightly # more ridiculous IMO. To save you from scrolling, this is the last part of the podspec. # TODO(jcanizales): Translate err_data_generate.go into a Bash or Ruby script. @@ -152,178 +264,166 @@ Pod::Spec.new do |s| OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); const uint32_t kOpenSSLReasonValues[] = { - 0xc3207ba, - 0xc3287d4, - 0xc3307e3, - 0xc3387f3, - 0xc340802, - 0xc34881b, - 0xc350827, - 0xc358844, - 0xc360856, - 0xc368864, - 0xc370874, - 0xc378881, - 0xc380891, - 0xc38889c, - 0xc3908b2, - 0xc3988c1, - 0xc3a08d5, - 0xc3a87c7, - 0xc3b00b0, - 0x10321478, - 0x10329484, - 0x1033149d, - 0x103394b0, - 0x10340de1, - 0x103494cf, - 0x103514e4, - 0x10359516, - 0x1036152f, - 0x10369544, - 0x10371562, - 0x10379571, - 0x1038158d, - 0x103895a8, - 0x103915b7, - 0x103995d3, - 0x103a15ee, - 0x103a9605, - 0x103b1616, - 0x103b962a, - 0x103c1649, - 0x103c9658, - 0x103d166f, - 0x103d9682, - 0x103e0b6c, - 0x103e96b3, - 0x103f16c6, - 0x103f96e0, - 0x104016f0, - 0x10409704, - 0x1041171a, - 0x10419732, - 0x10421747, - 0x1042975b, - 0x1043176d, - 0x104385d0, - 0x104408c1, - 0x10449782, - 0x10451799, - 0x104597ae, - 0x104617bc, - 0x10469695, - 0x104714f7, - 0x104787c7, - 0x104800b0, - 0x104894c3, - 0x14320b4f, - 0x14328b5d, - 0x14330b6c, - 0x14338b7e, + 0xc320838, + 0xc328852, + 0xc330861, + 0xc338871, + 0xc340880, + 0xc348899, + 0xc3508a5, + 0xc3588c2, + 0xc3608d4, + 0xc3688e2, + 0xc3708f2, + 0xc3788ff, + 0xc38090f, + 0xc38891a, + 0xc390930, + 0xc39893f, + 0xc3a0953, + 0xc3a8845, + 0xc3b00ea, + 0x10320845, + 0x103293ab, + 0x103313b7, + 0x103393d0, + 0x103413e3, + 0x10348e8b, + 0x10350c19, + 0x103593f6, + 0x1036140b, + 0x1036941e, + 0x1037143d, + 0x10379456, + 0x1038146b, + 0x10389489, + 0x10391498, + 0x103994b4, + 0x103a14cf, + 0x103a94de, + 0x103b14fa, + 0x103b9515, + 0x103c152c, + 0x103c80ea, + 0x103d153d, + 0x103d9551, + 0x103e1570, + 0x103e957f, + 0x103f1596, + 0x103f95a9, + 0x10400bea, + 0x104095bc, + 0x104115da, + 0x104195ed, + 0x10421607, + 0x10429617, + 0x1043162b, + 0x10439641, + 0x10441659, + 0x1044966e, + 0x10451682, + 0x10459694, + 0x104605fb, + 0x1046893f, + 0x104716a9, + 0x104796c0, + 0x104816d5, + 0x104896e3, + 0x14320bcd, + 0x14328bdb, + 0x14330bea, + 0x14338bfc, + 0x143400ac, + 0x143480ea, 0x18320083, - 0x18328e47, - 0x18340e75, - 0x18348e89, - 0x18358ec0, - 0x18368eed, - 0x18370f00, - 0x18378f14, - 0x18380f38, - 0x18388f46, - 0x18390f5c, - 0x18398f70, - 0x183a0f80, - 0x183b0f90, - 0x183b8fa5, - 0x183c8fd0, - 0x183d0fe4, - 0x183d8ff4, - 0x183e0b9b, - 0x183e9001, - 0x183f1013, - 0x183f901e, - 0x1840102e, - 0x1840903f, - 0x18411050, - 0x18419062, - 0x1842108b, - 0x184290bd, - 0x184310cc, - 0x18451135, - 0x1845914b, - 0x18461166, - 0x18468ed8, - 0x184709d9, - 0x18478094, - 0x18480fbc, - 0x18489101, - 0x18490e5d, - 0x18498e9e, - 0x184a119c, - 0x184a9119, - 0x184b10e0, - 0x184b8e37, - 0x184c10a4, - 0x184c866b, - 0x184d1181, - 0x203211c3, - 0x243211cf, - 0x24328907, - 0x243311e1, - 0x243391ee, - 0x243411fb, - 0x2434920d, - 0x2435121c, - 0x24359239, - 0x24361246, - 0x24369254, - 0x24371262, - 0x24379270, - 0x24381279, - 0x24389286, - 0x24391299, - 0x28320b8f, - 0x28328b9b, - 0x28330b6c, - 0x28338bae, - 0x2c322c0b, - 0x2c32ac19, - 0x2c332c2b, - 0x2c33ac3d, - 0x2c342c51, - 0x2c34ac63, - 0x2c352c7e, - 0x2c35ac90, - 0x2c362ca3, - 0x2c3682f3, - 0x2c372cb0, - 0x2c37acc2, - 0x2c382cd5, - 0x2c38ace3, - 0x2c392cf3, - 0x2c39ad05, - 0x2c3a2d19, - 0x2c3aad2a, - 0x2c3b1359, - 0x2c3bad3b, - 0x2c3c2d4f, - 0x2c3cad65, - 0x2c3d2d7e, - 0x2c3dadac, - 0x2c3e2dba, - 0x2c3eadd2, - 0x2c3f2dea, - 0x2c3fadf7, - 0x2c402e1a, - 0x2c40ae39, - 0x2c4111c3, - 0x2c41ae4a, - 0x2c422e5d, - 0x2c429135, - 0x2c432e6e, - 0x2c4386a2, - 0x2c442d9b, + 0x18328ee1, + 0x183300ac, + 0x18338ef7, + 0x18340f0b, + 0x183480ea, + 0x18350f20, + 0x18358f38, + 0x18360f4d, + 0x18368f61, + 0x18370f85, + 0x18378f9b, + 0x18380faf, + 0x18388fbf, + 0x18390a57, + 0x18398fcf, + 0x183a0fe4, + 0x183a8ff8, + 0x183b0c25, + 0x183b9005, + 0x183c1017, + 0x183c9022, + 0x183d1032, + 0x183d9043, + 0x183e1054, + 0x183e9066, + 0x183f108f, + 0x183f90a8, + 0x184010c0, + 0x184086d3, + 0x203210e7, + 0x243210f3, + 0x24328985, + 0x24331105, + 0x24339112, + 0x2434111f, + 0x24349131, + 0x24351140, + 0x2435915d, + 0x2436116a, + 0x24369178, + 0x24371186, + 0x24379194, + 0x2438119d, + 0x243891aa, + 0x243911bd, + 0x28320c0d, + 0x28328c25, + 0x28330bea, + 0x28338c38, + 0x28340c19, + 0x283480ac, + 0x283500ea, + 0x2c3227cb, + 0x2c32a7d9, + 0x2c3327eb, + 0x2c33a7fd, + 0x2c342811, + 0x2c34a823, + 0x2c35283e, + 0x2c35a850, + 0x2c362863, + 0x2c36832d, + 0x2c372870, + 0x2c37a882, + 0x2c382895, + 0x2c38a8ac, + 0x2c3928ba, + 0x2c39a8ca, + 0x2c3a28dc, + 0x2c3aa8f0, + 0x2c3b2901, + 0x2c3ba920, + 0x2c3c2934, + 0x2c3ca94a, + 0x2c3d2963, + 0x2c3da980, + 0x2c3e2991, + 0x2c3ea99f, + 0x2c3f29b7, + 0x2c3fa9cf, + 0x2c4029dc, + 0x2c4090e7, + 0x2c4129ed, + 0x2c41aa00, + 0x2c4210c0, + 0x2c42aa11, + 0x2c430720, + 0x2c43a912, 0x30320000, 0x30328015, 0x3033001f, @@ -333,479 +433,454 @@ Pod::Spec.new do |s| 0x3035006b, 0x30358083, 0x30360094, - 0x303680a1, - 0x303700b0, - 0x303780bd, - 0x303800d0, - 0x303880eb, - 0x30390100, - 0x30398114, - 0x303a0128, - 0x303a8139, - 0x303b0152, - 0x303b816f, - 0x303c017d, - 0x303c8191, - 0x303d01a1, - 0x303d81ba, - 0x303e01ca, - 0x303e81dd, - 0x303f01ec, - 0x303f81f8, - 0x3040020d, - 0x3040821d, - 0x30410234, - 0x30418241, - 0x30420254, - 0x30428263, - 0x30430278, - 0x30438299, - 0x304402ac, - 0x304482bf, - 0x304502d8, - 0x304582f3, - 0x30460310, - 0x30468329, - 0x30470337, - 0x30478348, - 0x30480357, - 0x3048836f, - 0x30490381, - 0x30498395, - 0x304a03b4, - 0x304a83c7, - 0x304b03d2, - 0x304b83e1, - 0x304c03f2, - 0x304c83fe, - 0x304d0414, - 0x304d8422, - 0x304e0438, - 0x304e844a, - 0x304f045c, - 0x304f846f, - 0x30500482, - 0x30508493, - 0x305104a3, - 0x305184bb, - 0x305204d0, - 0x305284e8, - 0x305304fc, - 0x30538514, - 0x3054052d, - 0x30548546, - 0x30550563, - 0x3055856e, - 0x30560586, - 0x30568596, - 0x305705a7, - 0x305785ba, - 0x305805d0, - 0x305885d9, - 0x305905ee, - 0x30598601, - 0x305a0610, - 0x305a8630, - 0x305b063f, - 0x305b864b, - 0x305c066b, - 0x305c8687, - 0x305d0698, - 0x305d86a2, - 0x34320ac9, - 0x34328add, - 0x34330afa, - 0x34338b0d, - 0x34340b1c, - 0x34348b39, + 0x303680ac, + 0x303700b9, + 0x303780c8, + 0x303800ea, + 0x303880f7, + 0x3039010a, + 0x30398125, + 0x303a013a, + 0x303a814e, + 0x303b0162, + 0x303b8173, + 0x303c018c, + 0x303c81a9, + 0x303d01b7, + 0x303d81cb, + 0x303e01db, + 0x303e81f4, + 0x303f0204, + 0x303f8217, + 0x30400226, + 0x30408232, + 0x30410247, + 0x30418257, + 0x3042026e, + 0x3042827b, + 0x3043028e, + 0x3043829d, + 0x304402b2, + 0x304482d3, + 0x304502e6, + 0x304582f9, + 0x30460312, + 0x3046832d, + 0x3047034a, + 0x30478363, + 0x30480371, + 0x30488382, + 0x30490391, + 0x304983a9, + 0x304a03bb, + 0x304a83cf, + 0x304b03ee, + 0x304b8401, + 0x304c040c, + 0x304c841d, + 0x304d0429, + 0x304d843f, + 0x304e044d, + 0x304e8463, + 0x304f0475, + 0x304f8487, + 0x3050049a, + 0x305084ad, + 0x305104be, + 0x305184ce, + 0x305204e6, + 0x305284fb, + 0x30530513, + 0x30538527, + 0x3054053f, + 0x30548558, + 0x30550571, + 0x3055858e, + 0x30560599, + 0x305685b1, + 0x305705c1, + 0x305785d2, + 0x305805e5, + 0x305885fb, + 0x30590604, + 0x30598619, + 0x305a062c, + 0x305a863b, + 0x305b065b, + 0x305b866a, + 0x305c068b, + 0x305c86a7, + 0x305d06b3, + 0x305d86d3, + 0x305e06ef, + 0x305e8700, + 0x305f0716, + 0x305f8720, + 0x34320b47, + 0x34328b5b, + 0x34330b78, + 0x34338b8b, + 0x34340b9a, + 0x34348bb7, 0x3c320083, - 0x3c328bd8, - 0x3c330bf1, - 0x3c338c0c, - 0x3c340c29, - 0x3c348c44, - 0x3c350c5f, - 0x3c358c74, - 0x3c360c8d, - 0x3c368ca5, - 0x3c370cb6, - 0x3c378cc4, - 0x3c380cd1, - 0x3c388ce5, - 0x3c390b9b, - 0x3c398cf9, - 0x3c3a0d0d, - 0x3c3a8881, - 0x3c3b0d1d, - 0x3c3b8d38, - 0x3c3c0d4a, - 0x3c3c8d60, - 0x3c3d0d6a, - 0x3c3d8d7e, - 0x3c3e0d8c, - 0x3c3e8db1, - 0x3c3f0bc4, - 0x3c3f8d9a, - 0x403217d3, - 0x403297e9, - 0x40331817, - 0x40339821, - 0x40341838, - 0x40349856, - 0x40351866, - 0x40359878, - 0x40361885, - 0x40369891, - 0x403718a6, - 0x403798bb, - 0x403818cd, - 0x403898d8, - 0x403918ea, - 0x40398de1, - 0x403a18fa, - 0x403a990d, - 0x403b192e, - 0x403b993f, - 0x403c194f, - 0x403c8064, - 0x403d195b, - 0x403d9977, - 0x403e198d, - 0x403e999c, - 0x403f19af, - 0x403f99c9, - 0x404019d7, - 0x404099ec, - 0x40411a00, - 0x40419a1d, - 0x40421a36, - 0x40429a51, - 0x40431a6a, - 0x40439a7d, - 0x40441a91, - 0x40449aa9, - 0x40451af4, - 0x40459b02, - 0x40461b20, - 0x40468094, - 0x40471b35, - 0x40479b47, - 0x40481b6b, - 0x40489b99, - 0x40491bad, - 0x40499bc2, - 0x404a1bdb, - 0x404a9c15, - 0x404b1c46, - 0x404b9c7c, - 0x404c1c97, - 0x404c9cb1, - 0x404d1cc8, - 0x404d9cf0, - 0x404e1d07, - 0x404e9d23, - 0x404f1d3f, - 0x404f9d60, - 0x40501d82, - 0x40509d9e, - 0x40511db2, - 0x40519dbf, - 0x40521dd6, - 0x40529de6, - 0x40531df6, - 0x40539e0a, - 0x40541e25, - 0x40549e35, - 0x40551e4c, - 0x40559e5b, - 0x40561e88, - 0x40569ea0, - 0x40571ebc, - 0x40579ed5, - 0x40581ee8, - 0x40589efd, - 0x40591f20, - 0x40599f4b, - 0x405a1f58, - 0x405a9f71, - 0x405b1f89, - 0x405b9f9c, - 0x405c1fb1, - 0x405c9fc3, - 0x405d1fd8, - 0x405d9fe8, - 0x405e2001, - 0x405ea015, - 0x405f2025, - 0x405fa03d, - 0x4060204e, - 0x4060a061, - 0x40612072, - 0x4061a090, - 0x406220a1, - 0x4062a0ae, - 0x406320c5, - 0x4063a106, - 0x4064211d, - 0x4064a12a, - 0x40652138, - 0x4065a15a, - 0x40662182, - 0x4066a197, - 0x406721ae, - 0x4067a1bf, - 0x406821d0, - 0x4068a1e1, - 0x406921f6, - 0x4069a20d, - 0x406a221e, - 0x406aa237, - 0x406b2252, - 0x406ba269, - 0x406c22d6, - 0x406ca2f7, - 0x406d230a, - 0x406da32b, - 0x406e2346, - 0x406ea38f, - 0x406f23b0, - 0x406fa3d6, - 0x407023f6, - 0x4070a412, - 0x4071259f, - 0x4071a5c2, - 0x407225d8, - 0x4072a5f7, - 0x4073260f, - 0x4073a62f, - 0x40742859, - 0x4074a87e, - 0x40752899, - 0x4075a8b8, - 0x407628e7, - 0x4076a90f, - 0x40772940, - 0x4077a95f, - 0x40782999, - 0x4078a9b0, - 0x407929c3, - 0x4079a9e0, - 0x407a0782, - 0x407aa9f2, - 0x407b2a05, - 0x407baa1e, - 0x407c2a36, - 0x407c90bd, - 0x407d2a4a, - 0x407daa64, - 0x407e2a75, - 0x407eaa89, - 0x407f2a97, - 0x407faab2, - 0x40801286, - 0x4080aad7, - 0x40812af9, - 0x4081ab14, - 0x40822b29, - 0x4082ab41, - 0x40832b59, - 0x4083ab70, - 0x40842b86, - 0x4084ab92, - 0x40852ba5, - 0x4085abba, - 0x40862bcc, - 0x4086abe1, - 0x40872bea, - 0x40879cde, - 0x40880083, - 0x4088a0e5, - 0x40890a17, - 0x4089a281, - 0x408a1bfe, - 0x408aa2ab, - 0x408b2928, - 0x408ba984, - 0x408c2361, - 0x408c9c2f, - 0x408d1c64, - 0x408d9e76, - 0x408e1ab9, - 0x408e9add, - 0x408f1f2e, - 0x408f9b8b, - 0x41f424ca, - 0x41f9255c, - 0x41fe244f, - 0x41fea680, - 0x41ff2771, - 0x420324e3, - 0x42082505, - 0x4208a541, - 0x42092433, - 0x4209a57b, - 0x420a248a, - 0x420aa46a, - 0x420b24aa, - 0x420ba523, - 0x420c278d, - 0x420ca64d, - 0x420d2667, - 0x420da69e, - 0x421226b8, - 0x42172754, - 0x4217a6fa, - 0x421c271c, - 0x421f26d7, - 0x422127a4, - 0x42262737, - 0x422b283d, - 0x422ba806, - 0x422c2825, - 0x422ca7e0, - 0x422d27bf, - 0x443206ad, - 0x443286bc, - 0x443306c8, - 0x443386d6, - 0x443406e9, - 0x443486fa, - 0x44350701, - 0x4435870b, - 0x4436071e, - 0x44368734, - 0x44370746, - 0x44378753, - 0x44380762, - 0x4438876a, - 0x44390782, - 0x44398790, - 0x443a07a3, - 0x4c3212b0, - 0x4c3292c0, - 0x4c3312d3, - 0x4c3392f3, - 0x4c340094, - 0x4c3480b0, - 0x4c3512ff, - 0x4c35930d, - 0x4c361329, - 0x4c36933c, - 0x4c37134b, - 0x4c379359, - 0x4c38136e, - 0x4c38937a, - 0x4c39139a, - 0x4c3993c4, - 0x4c3a13dd, - 0x4c3a93f6, - 0x4c3b05d0, - 0x4c3b940f, - 0x4c3c1421, - 0x4c3c9430, - 0x4c3d10bd, - 0x4c3d9449, - 0x4c3e1456, - 0x50322e80, - 0x5032ae8f, - 0x50332e9a, - 0x5033aeaa, - 0x50342ec3, - 0x5034aedd, - 0x50352eeb, - 0x5035af01, - 0x50362f13, - 0x5036af29, - 0x50372f42, - 0x5037af55, - 0x50382f6d, - 0x5038af7e, - 0x50392f93, - 0x5039afa7, - 0x503a2fc7, - 0x503aafdd, - 0x503b2ff5, - 0x503bb007, - 0x503c3023, - 0x503cb03a, - 0x503d3053, - 0x503db069, - 0x503e3076, - 0x503eb08c, - 0x503f309e, - 0x503f8348, - 0x504030b1, - 0x5040b0c1, - 0x504130db, - 0x5041b0ea, - 0x50423104, - 0x5042b121, - 0x50433131, - 0x5043b141, - 0x50443150, - 0x50448414, - 0x50453164, - 0x5045b182, - 0x50463195, - 0x5046b1ab, - 0x504731bd, - 0x5047b1d2, - 0x504831f8, - 0x5048b206, - 0x50493219, - 0x5049b22e, - 0x504a3244, - 0x504ab254, - 0x504b3274, - 0x504bb287, - 0x504c32aa, - 0x504cb2d8, - 0x504d32ea, - 0x504db307, - 0x504e3322, - 0x504eb33e, - 0x504f3350, - 0x504fb367, - 0x50503376, - 0x50508687, - 0x50513389, - 0x58320e1f, - 0x68320de1, - 0x68328b9b, - 0x68330bae, - 0x68338def, - 0x68340dff, - 0x683480b0, - 0x6c320dbd, - 0x6c328b7e, - 0x6c330dc8, - 0x7432098d, - 0x783208f2, - 0x78328907, - 0x78330913, + 0x3c328c62, + 0x3c330c7b, + 0x3c338c96, + 0x3c340cb3, + 0x3c348cdd, + 0x3c350cf8, + 0x3c358d1e, + 0x3c360d37, + 0x3c368d4f, + 0x3c370d60, + 0x3c378d6e, + 0x3c380d7b, + 0x3c388d8f, + 0x3c390c25, + 0x3c398da3, + 0x3c3a0db7, + 0x3c3a88ff, + 0x3c3b0dc7, + 0x3c3b8de2, + 0x3c3c0df4, + 0x3c3c8e0a, + 0x3c3d0e14, + 0x3c3d8e28, + 0x3c3e0e36, + 0x3c3e8e5b, + 0x3c3f0c4e, + 0x3c3f8e44, + 0x3c4000ac, + 0x3c4080ea, + 0x3c410cce, + 0x3c418d0d, + 0x403216fa, + 0x40329710, + 0x4033173e, + 0x40339748, + 0x4034175f, + 0x4034977d, + 0x4035178d, + 0x4035979f, + 0x403617ac, + 0x403697b8, + 0x403717cd, + 0x403797df, + 0x403817ea, + 0x403897fc, + 0x40390e8b, + 0x4039980c, + 0x403a181f, + 0x403a9840, + 0x403b1851, + 0x403b9861, + 0x403c0064, + 0x403c8083, + 0x403d186d, + 0x403d9883, + 0x403e1892, + 0x403e98a5, + 0x403f18bf, + 0x403f98cd, + 0x404018e2, + 0x404098f6, + 0x40411913, + 0x4041992e, + 0x40421947, + 0x4042995a, + 0x4043196e, + 0x40439986, + 0x4044199d, + 0x404480ac, + 0x404519b2, + 0x404599c4, + 0x404619e8, + 0x40469a08, + 0x40471a16, + 0x40479a3d, + 0x40481a52, + 0x40489a6b, + 0x40491a82, + 0x40499a9c, + 0x404a1ab3, + 0x404a9ad1, + 0x404b1ae9, + 0x404b9b00, + 0x404c1b16, + 0x404c9b28, + 0x404d1b49, + 0x404d9b6b, + 0x404e1b7f, + 0x404e9b8c, + 0x404f1ba3, + 0x404f9bb3, + 0x40501bdd, + 0x40509bf1, + 0x40511c0c, + 0x40519c1c, + 0x40521c33, + 0x40529c45, + 0x40531c5d, + 0x40539c70, + 0x40541c85, + 0x40549ca8, + 0x40551cb6, + 0x40559cd3, + 0x40561ce0, + 0x40569cf9, + 0x40571d11, + 0x40579d24, + 0x40581d39, + 0x40589d4b, + 0x40591d7a, + 0x40599d93, + 0x405a1da7, + 0x405a9db7, + 0x405b1dcf, + 0x405b9de0, + 0x405c1df3, + 0x405c9e04, + 0x405d1e11, + 0x405d9e28, + 0x405e1e48, + 0x405e8a95, + 0x405f1e69, + 0x405f9e76, + 0x40601e84, + 0x40609ea6, + 0x40611ece, + 0x40619ee3, + 0x40621efa, + 0x40629f0b, + 0x40631f1c, + 0x40639f31, + 0x40641f48, + 0x40649f59, + 0x40651f74, + 0x40659f8b, + 0x40661fa3, + 0x40669fcd, + 0x40671ff8, + 0x4067a019, + 0x4068202c, + 0x4068a04d, + 0x4069207f, + 0x4069a0ad, + 0x406a20ce, + 0x406aa0ee, + 0x406b2276, + 0x406ba299, + 0x406c22af, + 0x406ca4db, + 0x406d250a, + 0x406da532, + 0x406e254b, + 0x406ea563, + 0x406f2582, + 0x406fa597, + 0x407025aa, + 0x4070a5c7, + 0x40710800, + 0x4071a5d9, + 0x407225ec, + 0x4072a605, + 0x4073261d, + 0x4073936d, + 0x40742631, + 0x4074a64b, + 0x4075265c, + 0x4075a670, + 0x4076267e, + 0x407691aa, + 0x407726a3, + 0x4077a6c5, + 0x407826e0, + 0x4078a719, + 0x40792730, + 0x4079a746, + 0x407a2752, + 0x407aa765, + 0x407b277a, + 0x407ba78c, + 0x407c27a1, + 0x407ca7aa, + 0x407d2068, + 0x407d9bc3, + 0x407e26f5, + 0x407e9d5b, + 0x407f1a2a, + 0x41f421a1, + 0x41f92233, + 0x41fe2126, + 0x41fea302, + 0x41ff23f3, + 0x420321ba, + 0x420821dc, + 0x4208a218, + 0x4209210a, + 0x4209a252, + 0x420a2161, + 0x420aa141, + 0x420b2181, + 0x420ba1fa, + 0x420c240f, + 0x420ca2cf, + 0x420d22e9, + 0x420da320, + 0x4212233a, + 0x421723d6, + 0x4217a37c, + 0x421c239e, + 0x421f2359, + 0x42212426, + 0x422623b9, + 0x422b24bf, + 0x422ba488, + 0x422c24a7, + 0x422ca462, + 0x422d2441, + 0x4432072b, + 0x4432873a, + 0x44330746, + 0x44338754, + 0x44340767, + 0x44348778, + 0x4435077f, + 0x44358789, + 0x4436079c, + 0x443687b2, + 0x443707c4, + 0x443787d1, + 0x443807e0, + 0x443887e8, + 0x44390800, + 0x4439880e, + 0x443a0821, + 0x4c3211d4, + 0x4c3291e4, + 0x4c3311f7, + 0x4c339217, + 0x4c3400ac, + 0x4c3480ea, + 0x4c351223, + 0x4c359231, + 0x4c36124d, + 0x4c369260, + 0x4c37126f, + 0x4c37927d, + 0x4c381292, + 0x4c38929e, + 0x4c3912be, + 0x4c3992e8, + 0x4c3a1301, + 0x4c3a931a, + 0x4c3b05fb, + 0x4c3b9333, + 0x4c3c1345, + 0x4c3c9354, + 0x4c3d136d, + 0x4c3d937c, + 0x4c3e1389, + 0x50322a23, + 0x5032aa32, + 0x50332a3d, + 0x5033aa4d, + 0x50342a66, + 0x5034aa80, + 0x50352a8e, + 0x5035aaa4, + 0x50362ab6, + 0x5036aacc, + 0x50372ae5, + 0x5037aaf8, + 0x50382b10, + 0x5038ab21, + 0x50392b36, + 0x5039ab4a, + 0x503a2b6a, + 0x503aab80, + 0x503b2b98, + 0x503babaa, + 0x503c2bc6, + 0x503cabdd, + 0x503d2bf6, + 0x503dac0c, + 0x503e2c19, + 0x503eac2f, + 0x503f2c41, + 0x503f8382, + 0x50402c54, + 0x5040ac64, + 0x50412c7e, + 0x5041ac8d, + 0x50422ca7, + 0x5042acc4, + 0x50432cd4, + 0x5043ace4, + 0x50442cf3, + 0x5044843f, + 0x50452d07, + 0x5045ad25, + 0x50462d38, + 0x5046ad4e, + 0x50472d60, + 0x5047ad75, + 0x50482d9b, + 0x5048ada9, + 0x50492dbc, + 0x5049add1, + 0x504a2de7, + 0x504aadf7, + 0x504b2e17, + 0x504bae2a, + 0x504c2e4d, + 0x504cae7b, + 0x504d2e8d, + 0x504daeaa, + 0x504e2ec5, + 0x504eaee1, + 0x504f2ef3, + 0x504faf0a, + 0x50502f19, + 0x505086ef, + 0x50512f2c, + 0x58320ec9, + 0x68320e8b, + 0x68328c25, + 0x68330c38, + 0x68338e99, + 0x68340ea9, + 0x683480ea, + 0x6c320e67, + 0x6c328bfc, + 0x6c330e72, + 0x74320a0b, + 0x78320970, + 0x78328985, + 0x78330991, 0x78338083, - 0x78340922, - 0x78348937, - 0x78350956, - 0x78358978, - 0x7836098d, - 0x783689a3, - 0x783709b3, - 0x783789c6, - 0x783809d9, - 0x783889eb, - 0x783909f8, - 0x78398a17, - 0x783a0a2c, - 0x783a8a3a, - 0x783b0a44, - 0x783b8a58, - 0x783c0a6f, - 0x783c8a84, - 0x783d0a9b, - 0x783d8ab0, - 0x783e0a06, - 0x7c3211b2, + 0x783409a0, + 0x783489b5, + 0x783509d4, + 0x783589f6, + 0x78360a0b, + 0x78368a21, + 0x78370a31, + 0x78378a44, + 0x78380a57, + 0x78388a69, + 0x78390a76, + 0x78398a95, + 0x783a0aaa, + 0x783a8ab8, + 0x783b0ac2, + 0x783b8ad6, + 0x783c0aed, + 0x783c8b02, + 0x783d0b19, + 0x783d8b2e, + 0x783e0a84, + 0x7c3210d6, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); @@ -819,8 +894,10 @@ Pod::Spec.new do |s| "BN_LIB\\0" "BOOLEAN_IS_WRONG_LENGTH\\0" "BUFFER_TOO_SMALL\\0" + "CONTEXT_NOT_INITIALISED\\0" "DECODE_ERROR\\0" "DEPTH_EXCEEDED\\0" + "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\\0" "ENCODE_ERROR\\0" "ERROR_GETTING_TIME\\0" "EXPECTING_AN_ASN1_SEQUENCE\\0" @@ -861,7 +938,6 @@ Pod::Spec.new do |s| "INVALID_UNIVERSALSTRING_LENGTH\\0" "INVALID_UTF8STRING\\0" "LIST_ERROR\\0" - "MALLOC_FAILURE\\0" "MISSING_ASN1_EOS\\0" "MISSING_EOC\\0" "MISSING_SECOND_NUMBER\\0" @@ -893,10 +969,13 @@ Pod::Spec.new do |s| "UNEXPECTED_EOC\\0" "UNIVERSALSTRING_IS_WRONG_LENGTH\\0" "UNKNOWN_FORMAT\\0" + "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\\0" + "UNKNOWN_SIGNATURE_ALGORITHM\\0" "UNKNOWN_TAG\\0" "UNSUPPORTED_ANY_DEFINED_BY_TYPE\\0" "UNSUPPORTED_PUBLIC_KEY_TYPE\\0" "UNSUPPORTED_TYPE\\0" + "WRONG_PUBLIC_KEY_TYPE\\0" "WRONG_TAG\\0" "WRONG_TYPE\\0" "BAD_FOPEN_MODE\\0" @@ -969,6 +1048,7 @@ Pod::Spec.new do |s| "MODULUS_TOO_LARGE\\0" "NO_PRIVATE_VALUE\\0" "BAD_Q_VALUE\\0" + "BAD_VERSION\\0" "MISSING_PARAMETERS\\0" "NEED_NEW_SETUP_VALUES\\0" "BIGNUM_OUT_OF_RANGE\\0" @@ -976,8 +1056,10 @@ Pod::Spec.new do |s| "D2I_ECPKPARAMETERS_FAILURE\\0" "EC_GROUP_NEW_BY_NAME_FAILURE\\0" "GROUP2PKPARAMETERS_FAILURE\\0" + "GROUP_MISMATCH\\0" "I2D_ECPKPARAMETERS_FAILURE\\0" "INCOMPATIBLE_OBJECTS\\0" + "INVALID_COFACTOR\\0" "INVALID_COMPRESSED_POINT\\0" "INVALID_COMPRESSION_BIT\\0" "INVALID_ENCODING\\0" @@ -1002,27 +1084,19 @@ Pod::Spec.new do |s| "NOT_IMPLEMENTED\\0" "RANDOM_NUMBER_GENERATION_FAILED\\0" "OPERATION_NOT_SUPPORTED\\0" - "BN_DECODE_ERROR\\0" "COMMAND_NOT_SUPPORTED\\0" - "CONTEXT_NOT_INITIALISED\\0" "DIFFERENT_KEY_TYPES\\0" "DIFFERENT_PARAMETERS\\0" - "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\\0" "EXPECTING_AN_EC_KEY_KEY\\0" "EXPECTING_AN_RSA_KEY\\0" - "EXPECTING_A_DH_KEY\\0" "EXPECTING_A_DSA_KEY\\0" "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\\0" - "INVALID_CURVE\\0" "INVALID_DIGEST_LENGTH\\0" "INVALID_DIGEST_TYPE\\0" "INVALID_KEYBITS\\0" "INVALID_MGF1_MD\\0" "INVALID_PADDING_MODE\\0" - "INVALID_PSS_PARAMETERS\\0" "INVALID_PSS_SALTLEN\\0" - "INVALID_SALT_LENGTH\\0" - "INVALID_TRAILER\\0" "KEYS_NOT_SET\\0" "NO_DEFAULT_DIGEST\\0" "NO_KEY_SET\\0" @@ -1032,17 +1106,8 @@ Pod::Spec.new do |s| "NO_PARAMETERS_SET\\0" "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\\0" "OPERATON_NOT_INITIALIZED\\0" - "PARAMETER_ENCODING_ERROR\\0" - "UNKNOWN_DIGEST\\0" - "UNKNOWN_MASK_DIGEST\\0" - "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\\0" "UNKNOWN_PUBLIC_KEY_TYPE\\0" - "UNKNOWN_SIGNATURE_ALGORITHM\\0" "UNSUPPORTED_ALGORITHM\\0" - "UNSUPPORTED_MASK_ALGORITHM\\0" - "UNSUPPORTED_MASK_PARAMETER\\0" - "UNSUPPORTED_SIGNATURE_TYPE\\0" - "WRONG_PUBLIC_KEY_TYPE\\0" "OUTPUT_TOO_LARGE\\0" "UNKNOWN_NID\\0" "BAD_BASE64_DECODE\\0" @@ -1078,13 +1143,13 @@ Pod::Spec.new do |s| "UNKNOWN_ALGORITHM\\0" "UNKNOWN_CIPHER\\0" "UNKNOWN_CIPHER_ALGORITHM\\0" + "UNKNOWN_DIGEST\\0" "UNKNOWN_HASH\\0" "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\\0" "BAD_E_VALUE\\0" "BAD_FIXED_HEADER_DECRYPT\\0" "BAD_PAD_BYTE_COUNT\\0" "BAD_RSA_PARAMETERS\\0" - "BAD_VERSION\\0" "BLOCK_TYPE_IS_NOT_01\\0" "BN_NOT_INITIALIZED\\0" "CANNOT_RECOVER_MULTI_PRIME_KEY\\0" @@ -1129,7 +1194,6 @@ Pod::Spec.new do |s| "BAD_DIGEST_LENGTH\\0" "BAD_ECC_CERT\\0" "BAD_ECPOINT\\0" - "BAD_HANDSHAKE_LENGTH\\0" "BAD_HANDSHAKE_RECORD\\0" "BAD_HELLO_REQUEST\\0" "BAD_LENGTH\\0" @@ -1140,7 +1204,6 @@ Pod::Spec.new do |s| "BAD_SSL_FILETYPE\\0" "BAD_WRITE_RETRY\\0" "BIO_NOT_SET\\0" - "CANNOT_SERIALIZE_PUBLIC_KEY\\0" "CA_DN_LENGTH_MISMATCH\\0" "CA_DN_TOO_LONG\\0" "CCS_RECEIVED_EARLY\\0" @@ -1149,57 +1212,43 @@ Pod::Spec.new do |s| "CERT_LENGTH_MISMATCH\\0" "CHANNEL_ID_NOT_P256\\0" "CHANNEL_ID_SIGNATURE_INVALID\\0" - "CIPHER_CODE_WRONG_LENGTH\\0" "CIPHER_OR_HASH_UNAVAILABLE\\0" "CLIENTHELLO_PARSE_FAILED\\0" "CLIENTHELLO_TLSEXT\\0" "CONNECTION_REJECTED\\0" "CONNECTION_TYPE_NOT_SET\\0" - "COOKIE_MISMATCH\\0" - "CUSTOM_EXTENSION_CONTENTS_TOO_LARGE\\0" "CUSTOM_EXTENSION_ERROR\\0" - "D2I_ECDSA_SIG\\0" - "DATA_BETWEEN_CCS_AND_FINISHED\\0" "DATA_LENGTH_TOO_LONG\\0" "DECRYPTION_FAILED\\0" "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\\0" "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0" "DH_P_TOO_LONG\\0" "DIGEST_CHECK_FAILED\\0" + "DOWNGRADE_DETECTED\\0" "DTLS_MESSAGE_TOO_BIG\\0" "ECC_CERT_NOT_FOR_SIGNING\\0" - "EMPTY_SRTP_PROTECTION_PROFILE_LIST\\0" "EMS_STATE_INCONSISTENT\\0" "ENCRYPTED_LENGTH_TOO_LONG\\0" "ERROR_ADDING_EXTENSION\\0" "ERROR_IN_RECEIVED_CIPHER_LIST\\0" "ERROR_PARSING_EXTENSION\\0" - "EVP_DIGESTSIGNFINAL_FAILED\\0" - "EVP_DIGESTSIGNINIT_FAILED\\0" "EXCESSIVE_MESSAGE_SIZE\\0" "EXTRA_DATA_IN_MESSAGE\\0" "FRAGMENT_MISMATCH\\0" - "GOT_A_FIN_BEFORE_A_CCS\\0" - "GOT_CHANNEL_ID_BEFORE_A_CCS\\0" - "GOT_NEXT_PROTO_BEFORE_A_CCS\\0" "GOT_NEXT_PROTO_WITHOUT_EXTENSION\\0" "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\\0" - "HANDSHAKE_RECORD_BEFORE_CCS\\0" "HTTPS_PROXY_REQUEST\\0" "HTTP_REQUEST\\0" "INAPPROPRIATE_FALLBACK\\0" "INVALID_COMMAND\\0" "INVALID_MESSAGE\\0" + "INVALID_OUTER_RECORD_TYPE\\0" "INVALID_SSL_SESSION\\0" "INVALID_TICKET_KEYS_LENGTH\\0" "LENGTH_MISMATCH\\0" "LIBRARY_HAS_NO_CIPHERS\\0" - "MISSING_DH_KEY\\0" - "MISSING_ECDSA_SIGNING_CERT\\0" "MISSING_EXTENSION\\0" "MISSING_RSA_CERTIFICATE\\0" - "MISSING_RSA_ENCRYPTING_CERT\\0" - "MISSING_RSA_SIGNING_CERT\\0" "MISSING_TMP_DH_KEY\\0" "MISSING_TMP_ECDH_KEY\\0" "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\\0" @@ -1211,8 +1260,8 @@ Pod::Spec.new do |s| "NO_CERTIFICATE_SET\\0" "NO_CIPHERS_AVAILABLE\\0" "NO_CIPHERS_PASSED\\0" - "NO_CIPHERS_SPECIFIED\\0" "NO_CIPHER_MATCH\\0" + "NO_COMMON_SIGNATURE_ALGORITHMS\\0" "NO_COMPRESSION_SPECIFIED\\0" "NO_METHOD_SPECIFIED\\0" "NO_P256_SUPPORT\\0" @@ -1220,13 +1269,10 @@ Pod::Spec.new do |s| "NO_RENEGOTIATION\\0" "NO_REQUIRED_DIGEST\\0" "NO_SHARED_CIPHER\\0" - "NO_SHARED_SIGATURE_ALGORITHMS\\0" - "NO_SRTP_PROFILES\\0" "NULL_SSL_CTX\\0" "NULL_SSL_METHOD_PASSED\\0" "OLD_SESSION_CIPHER_NOT_RETURNED\\0" "OLD_SESSION_VERSION_NOT_RETURNED\\0" - "PACKET_LENGTH_TOO_LONG\\0" "PARSE_TLSEXT\\0" "PATH_TOO_LONG\\0" "PEER_DID_NOT_RETURN_A_CERTIFICATE\\0" @@ -1235,11 +1281,9 @@ Pod::Spec.new do |s| "PSK_IDENTITY_NOT_FOUND\\0" "PSK_NO_CLIENT_CB\\0" "PSK_NO_SERVER_CB\\0" - "READ_BIO_NOT_SET\\0" "READ_TIMEOUT_EXPIRED\\0" "RECORD_LENGTH_MISMATCH\\0" "RECORD_TOO_LARGE\\0" - "RENEGOTIATE_EXT_TOO_LONG\\0" "RENEGOTIATION_ENCODING_ERR\\0" "RENEGOTIATION_MISMATCH\\0" "REQUIRED_CIPHER_MISSING\\0" @@ -1249,13 +1293,11 @@ Pod::Spec.new do |s| "SERVERHELLO_TLSEXT\\0" "SESSION_ID_CONTEXT_UNINITIALIZED\\0" "SESSION_MAY_NOT_BE_CREATED\\0" - "SIGNATURE_ALGORITHMS_ERROR\\0" + "SHUTDOWN_WHILE_IN_INIT\\0" "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\\0" "SRTP_COULD_NOT_ALLOCATE_PROFILES\\0" - "SRTP_PROTECTION_PROFILE_LIST_TOO_LONG\\0" "SRTP_UNKNOWN_PROTECTION_PROFILE\\0" "SSL3_EXT_INVALID_SERVERNAME\\0" - "SSL3_EXT_INVALID_SERVERNAME_TYPE\\0" "SSLV3_ALERT_BAD_CERTIFICATE\\0" "SSLV3_ALERT_BAD_RECORD_MAC\\0" "SSLV3_ALERT_CERTIFICATE_EXPIRED\\0" @@ -1270,10 +1312,7 @@ Pod::Spec.new do |s| "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\\0" "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\\0" "SSL_HANDSHAKE_FAILURE\\0" - "SSL_SESSION_ID_CALLBACK_FAILED\\0" - "SSL_SESSION_ID_CONFLICT\\0" "SSL_SESSION_ID_CONTEXT_TOO_LONG\\0" - "SSL_SESSION_ID_HAS_BAD_LENGTH\\0" "TLSV1_ALERT_ACCESS_DENIED\\0" "TLSV1_ALERT_DECODE_ERROR\\0" "TLSV1_ALERT_DECRYPTION_FAILED\\0" @@ -1292,17 +1331,12 @@ Pod::Spec.new do |s| "TLSV1_CERTIFICATE_UNOBTAINABLE\\0" "TLSV1_UNRECOGNIZED_NAME\\0" "TLSV1_UNSUPPORTED_EXTENSION\\0" - "TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER\\0" - "TLS_ILLEGAL_EXPORTER_LABEL\\0" - "TLS_INVALID_ECPOINTFORMAT_LIST\\0" "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0" "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\\0" "TOO_MANY_EMPTY_FRAGMENTS\\0" "TOO_MANY_WARNING_ALERTS\\0" "UNABLE_TO_FIND_ECDH_PARAMETERS\\0" - "UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS\\0" "UNEXPECTED_EXTENSION\\0" - "UNEXPECTED_GROUP_CLOSE\\0" "UNEXPECTED_MESSAGE\\0" "UNEXPECTED_OPERATOR_IN_GROUP\\0" "UNEXPECTED_RECORD\\0" @@ -1314,13 +1348,11 @@ Pod::Spec.new do |s| "UNKNOWN_PROTOCOL\\0" "UNKNOWN_SSL_VERSION\\0" "UNKNOWN_STATE\\0" - "UNPROCESSED_HANDSHAKE_DATA\\0" "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\\0" "UNSUPPORTED_COMPRESSION_ALGORITHM\\0" "UNSUPPORTED_ELLIPTIC_CURVE\\0" "UNSUPPORTED_PROTOCOL\\0" - "UNSUPPORTED_SSL_VERSION\\0" - "USE_SRTP_NOT_NEGOTIATED\\0" + "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0" "WRONG_CERTIFICATE_TYPE\\0" "WRONG_CIPHER_RETURNED\\0" "WRONG_CURVE\\0" @@ -1341,12 +1373,14 @@ Pod::Spec.new do |s| "IDP_MISMATCH\\0" "INVALID_DIRECTORY\\0" "INVALID_FIELD_NAME\\0" + "INVALID_PSS_PARAMETERS\\0" "INVALID_TRUST\\0" "ISSUER_MISMATCH\\0" "KEY_TYPE_MISMATCH\\0" "KEY_VALUES_MISMATCH\\0" "LOADING_CERT_DIR\\0" "LOADING_DEFAULTS\\0" + "NAME_TOO_LONG\\0" "NEWER_CRL_NOT_NEWER\\0" "NOT_PKCS7_SIGNED_DATA\\0" "NO_CERTIFICATES_INCLUDED\\0" @@ -1356,8 +1390,6 @@ Pod::Spec.new do |s| "PUBLIC_KEY_DECODE_ERROR\\0" "PUBLIC_KEY_ENCODE_ERROR\\0" "SHOULD_RETRY\\0" - "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN\\0" - "UNABLE_TO_GET_CERTS_PUBLIC_KEY\\0" "UNKNOWN_KEY_TYPE\\0" "UNKNOWN_PURPOSE_ID\\0" "UNKNOWN_TRUST_ID\\0" diff --git a/src/objective-c/CronetFramework.podspec b/src/objective-c/CronetFramework.podspec index 20af7647f7..3ebcacf055 100644 --- a/src/objective-c/CronetFramework.podspec +++ b/src/objective-c/CronetFramework.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.license = { :type => 'BSD' } s.vendored_framework = "Cronet.framework" s.author = "The Chromium Authors" - s.ios.deployment_target = "8.0" + s.ios.deployment_target = "7.1" s.source = { :http => 'https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework.zip' } s.preserve_paths = "Cronet.framework" s.public_header_files = "Cronet.framework/Headers/**/*{.h}" diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index e9678f38a9..da9473f9a2 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -377,6 +377,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{NSLocalizedDescriptionKey: @"Connectivity lost."}]]; + [[GRPCHost hostWithAddress:strongSelf->_host] disconnect]; } }]; } diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index a3fa5938cd..97f6b89340 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -252,7 +252,7 @@ // Each completion queue consumes one thread. There's a trade to be made between creating and // consuming too many threads and having contention of multiple calls in a single completion - // queue. Currently we favor latency and use one per call. + // queue. Currently we use a singleton queue. _queue = [GRPCCompletionQueue completionQueue]; _call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path completionQueue:_queue]; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index fb0b566f19..83d1b655e8 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -33,7 +33,11 @@ #import "ProtoRPC.h" -#import <GPBProtocolBuffers.h> +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import <Protobuf/GPBProtocolBuffers.h> +#else + #import <GPBProtocolBuffers.h> +#endif #import <RxLibrary/GRXWriteable.h> #import <RxLibrary/GRXWriter+Transformations.h> diff --git a/src/objective-c/README.md b/src/objective-c/README.md index 30d9aad64c..6e917ddd81 100644 --- a/src/objective-c/README.md +++ b/src/objective-c/README.md @@ -1,12 +1,12 @@ [![Cocoapods](https://img.shields.io/cocoapods/v/gRPC.svg)](https://cocoapods.org/pods/gRPC) # gRPC for Objective-C -- [Install protoc with the gRPC plugin](#install) - [Write your API declaration in proto format](#write-protos) - [Integrate a proto library in your project](#cocoapods) - [Use the generated library in your code](#use) - [Use gRPC without Protobuf](#no-proto) -- [Alternative installation methods](#alternatives) +- [Alternatives to the steps above](#alternatives) + - [Install protoc with the gRPC plugin](#install) - [Install protoc and the gRPC plugin without using Homebrew](#no-homebrew) - [Integrate the generated gRPC library without using Cocoapods](#no-cocoapods) @@ -15,18 +15,6 @@ usage and adds some interoperability guarantees. Here we use [Protocol Buffers][ plugin for the Protobuf Compiler (_protoc_) to generate client libraries to communicate with gRPC services. -<a name="install"></a> -## Install protoc with the gRPC plugin - -On Mac OS X, install [homebrew][]. - -Run the following command to install _protoc_ and the gRPC _protoc_ plugin: -```sh -$ curl -fsSL https://goo.gl/getgrpc | bash - -``` -This will download and run the [gRPC install script][]. After the command completes, you're ready to -proceed. - <a name="write-protos"></a> ## Write your API declaration in proto format @@ -40,36 +28,74 @@ Install [Cocoapods](https://cocoapods.org/#install). You need to create a Podspec file for your proto library. You may simply copy the following example to the directory where your `.proto` files are located, updating the name, version and license as -necessary: +necessary. You also need to set the `pods_root` variable to the correct value, depending on where +you place this podspec relative to your Podfile. ```ruby Pod::Spec.new do |s| s.name = '<Podspec file name>' s.version = '0.0.1' s.license = '...' + s.authors = { '<your name>' => '<your email>' } + s.homepage = '...' + s.summary = '...' + s.source = { :git => 'https://github.com/...' } s.ios.deployment_target = '7.1' s.osx.deployment_target = '10.9' + # Base directory where the .proto files are. + src = '.' + + # We'll use protoc with the gRPC plugin. + s.dependency '!ProtoCompiler-gRPCPlugin', '~> 1.0.0-pre1' + + # Pods directory corresponding to this app's Podfile, relative to the location of this podspec. + pods_root = '<path to your Podfile>/Pods' + + # Path where Cocoapods downloads protoc and the gRPC plugin. + protoc_dir = "#{pods_root}/!ProtoCompiler" + protoc = "#{protoc_dir}/protoc" + plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin" + + # Directory where you want the generated files to be placed. This is an example. + dir = "#{pods_root}/#{s.name}" + # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. # You can run this command manually if you later change your protos and need to regenerate. - s.prepare_command = "protoc --objc_out=. --objcgrpc_out=. *.proto" + # Alternatively, you can advance the version of this podspec and run `pod update`. + s.prepare_command = <<-CMD + mkdir -p #{dir} + #{protoc} \ + --plugin=protoc-gen-grpc=#{plugin} \ + --objc_out=#{dir} \ + --grpc_out=#{dir} \ + -I #{src} \ + -I #{protoc_dir} \ + #{src}/*.proto + CMD # The --objc_out plugin generates a pair of .pbobjc.h/.pbobjc.m files for each .proto file. - s.subspec "Messages" do |ms| - ms.source_files = "*.pbobjc.{h,m}" - ms.header_mappings_dir = "." + s.subspec 'Messages' do |ms| + ms.source_files = "#{dir}/*.pbobjc.{h,m}" + ms.header_mappings_dir = dir ms.requires_arc = false - ms.dependency "Protobuf", "~> 3.0.0-alpha-4" + # The generated files depend on the protobuf runtime. + ms.dependency 'Protobuf' + # This is needed by all pods that depend on Protobuf: + ms.pod_target_xcconfig = { + 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', + } end # The --objcgrpc_out plugin generates a pair of .pbrpc.h/.pbrpc.m files for each .proto file with # a service defined. - s.subspec "Services" do |ss| - ss.source_files = "*.pbrpc.{h,m}" - ss.header_mappings_dir = "." + s.subspec 'Services' do |ss| + ss.source_files = "#{dir}/*.pbrpc.{h,m}" + ss.header_mappings_dir = dir ss.requires_arc = true - ss.dependency "gRPC", "~> 0.12" + # The generated files depend on the gRPC runtime, and on the files generated by `--objc_out`. + ss.dependency 'gRPC-ProtoRPC' ss.dependency "#{s.name}/Messages" end end @@ -81,11 +107,14 @@ Note: If your proto files are in a directory hierarchy, you might want to adjust the sample Podspec above. For example, you could use: ```ruby - s.prepare_command = "protoc --objc_out=. --objcgrpc_out=. *.proto **/*.proto" + s.prepare_command = <<-CMD + ... + #{src}/*.proto #{src}/**/*.proto + CMD ... - ms.source_files = "*.pbobjc.{h,m}", "**/*.pbobjc.{h,m}" + ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" ... - ss.source_files = "*.pbrpc.{h,m}", "**/*.pbrpc.{h,m}" + ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" ``` Once your library has a Podspec, Cocoapods can install it into any XCode project. For that, go into @@ -113,19 +142,33 @@ pod install <a name="use"></a> ## Use the generated library in your code -Please check this [sample app][] for examples of how to use a generated gRPC library. +Please check the [example apps][] for examples of how to use a generated gRPC library. <a name="no-proto"></a> ## Use gRPC without Protobuf -The [sample app][] has an example of how to use the generic gRPC Objective-C client without -generated files. +This [tests file](https://github.com/grpc/grpc/tree/master/src/objective-c/tests/GRPCClientTests.m) +shows how to use the generic gRPC Objective-C client without generated protobuf files. <a name="alternatives"></a> -## Alternative installation methods +## Alternatives to the steps above + +<a name="install"></a> +### Install _protoc_ with the gRPC plugin + +Although it's not recommended (because it can lead to hard-to-solve version conflicts), it is +sometimes more convenient to install _protoc_ and the gRPC plugin in your development machine, +instead of letting Cocoapods download the appropriate versions for you. To do so, on Mac OS X or +later, install [homebrew][]. + +The run the following command to install _protoc_ and the gRPC _protoc_ plugin: +```sh +$ curl -fsSL https://goo.gl/getgrpc | bash - +``` +This will download and run the [gRPC install script][]. <a name="no-homebrew"></a> -### Install protoc and the gRPC plugin without using Homebrew +### Install _protoc_ and the gRPC plugin without using Homebrew First install v3 of the Protocol Buffers compiler (_protoc_), by cloning [its Git repository](https://github.com/google/protobuf) and following these @@ -137,15 +180,15 @@ cloned. Compile the gRPC plugins for _protoc_: ```sh -make plugins +make grpc_objective_c_plugin ``` Create a symbolic link to the compiled plugin binary somewhere in your `$PATH`: ```sh ln -s `pwd`/bins/opt/grpc_objective_c_plugin /usr/local/bin/protoc-gen-objcgrpc ``` -(Notice that the name of the created link must begin with "protoc-gen-" for _protoc_ to recognize it -as a plugin). +(Notice that the name of the created link must begin with "`protoc-gen-`" for _protoc_ to recognize +it as a plugin). If you don't want to create the symbolic link, you can alternatively copy the binary (with the appropriate name). Or you might prefer instead to specify the plugin's path as a flag when invoking @@ -170,5 +213,5 @@ Objective-C Protobuf runtime library. [Protocol Buffers]:https://developers.google.com/protocol-buffers/ [homebrew]:http://brew.sh [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install -[example Podfile]:https://github.com/grpc/grpc/blob/master/src/objective-c/examples/Sample/Podfile -[sample app]: https://github.com/grpc/grpc/tree/master/src/objective-c/examples/Sample +[example Podfile]:https://github.com/grpc/grpc/blob/master/examples/objective-c/helloworld/Podfile +[example apps]: https://github.com/grpc/grpc/tree/master/examples/objective-c diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec index 107e6de4e2..7222a80b88 100644 --- a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec +++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec @@ -1,32 +1,51 @@ Pod::Spec.new do |s| - s.name = "RemoteTest" - s.version = "0.0.1" - s.license = "New BSD" + s.name = 'RemoteTest' + s.version = '0.0.1' + s.license = 'New BSD' s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' } - s.homepage = "http://www.grpc.io/" - s.summary = "RemoteTest example" + s.homepage = 'http://www.grpc.io/' + s.summary = 'RemoteTest example' s.source = { :git => 'https://github.com/grpc/grpc.git' } s.ios.deployment_target = '7.1' s.osx.deployment_target = '10.9' # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. + s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1" + + repo_root = '../../../..' + bin_dir = "#{repo_root}/bins/$CONFIG" + + protoc = "#{bin_dir}/protobuf/protoc" + well_known_types_dir = "#{repo_root}/third_party/protobuf/src" + plugin = "#{bin_dir}/grpc_objective_c_plugin" + s.prepare_command = <<-CMD - protoc --objc_out=. --objcgrpc_out=. *.proto + #{protoc} \ + --plugin=protoc-gen-grpc=#{plugin} \ + --objc_out=. \ + --grpc_out=. \ + -I . \ + -I #{well_known_types_dir} \ + *.proto CMD - s.subspec "Messages" do |ms| - ms.source_files = "*.pbobjc.{h,m}" - ms.header_mappings_dir = "." + s.subspec 'Messages' do |ms| + ms.source_files = '*.pbobjc.{h,m}' + ms.header_mappings_dir = '.' ms.requires_arc = false - ms.dependency "Protobuf", "~> 3.0.0-alpha-4" + ms.dependency 'Protobuf' + # This is needed by all pods that depend on Protobuf: + ms.pod_target_xcconfig = { + 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', + } end - s.subspec "Services" do |ss| - ss.source_files = "*.pbrpc.{h,m}" - ss.header_mappings_dir = "." + s.subspec 'Services' do |ss| + ss.source_files = '*.pbrpc.{h,m}' + ss.header_mappings_dir = '.' ss.requires_arc = true - ss.dependency "gRPC", "~> 0.12" + ss.dependency 'gRPC-ProtoRPC' ss.dependency "#{s.name}/Messages" end end diff --git a/src/objective-c/examples/RemoteTestClient/test.proto b/src/objective-c/examples/RemoteTestClient/test.proto index 514c3b8095..5c359c5c12 100644 --- a/src/objective-c/examples/RemoteTestClient/test.proto +++ b/src/objective-c/examples/RemoteTestClient/test.proto @@ -31,7 +31,7 @@ // of unary/streaming requests/responses. syntax = "proto3"; -import "empty.proto"; +import "google/protobuf/empty.proto"; import "messages.proto"; package grpc.testing; @@ -42,7 +42,7 @@ option objc_class_prefix = "RMT"; // performance with various types of payload. service TestService { // One empty request followed by one empty response. - rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); + rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty); // One request followed by one response. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); diff --git a/src/objective-c/examples/Sample/Podfile b/src/objective-c/examples/Sample/Podfile index 93859fb734..f6f0c00d5d 100644 --- a/src/objective-c/examples/Sample/Podfile +++ b/src/objective-c/examples/Sample/Podfile @@ -1,10 +1,48 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' -pod 'Protobuf', :path => "../../../../third_party/protobuf" -pod 'BoringSSL', :podspec => "../.." -pod 'gRPC', :path => "../../../.." -pod 'RemoteTest', :path => "../RemoteTestClient" +install! 'cocoapods', :deterministic_uuids => false + +use_frameworks! if ENV['FRAMEWORKS'] == 'YES' + +# Location of gRPC's repo root relative to this file. +GRPC_LOCAL_SRC = '../../../..' target 'Sample' do + # Depend on the generated RemoteTestClient library + pod 'RemoteTest', :path => "../RemoteTestClient" + + # Use the local versions of Protobuf, BoringSSL, and gRPC. You don't need any of the following + # lines in your application. + pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + + pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf" + + pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" + + pod 'gRPC', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core', :path => GRPC_LOCAL_SRC + pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC + pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC +end + +# This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in +# your application. +pre_install do |installer| + # This is the gRPC-Core podspec object, as initialized by its podspec file. + grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec + + # Copied from gRPC-Core.podspec, except for the adjusted src_root: + src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" + grpc_core_spec.pod_target_xcconfig = { + 'GRPC_SRC_ROOT' => src_root, + 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', + 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', + # If we don't set these two settings, `include/grpc/support/time.h` and + # `src/core/lib/support/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the + # build. + 'USE_HEADERMAP' => 'NO', + 'ALWAYS_SEARCH_USER_PATHS' => 'NO', + } end diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj index 5c2a6d14f9..ab7159cda2 100644 --- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C20055928615A6F8434E26B4 /* libPods-Sample.a */; }; + 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */; }; 6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; }; 6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; }; 6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; }; @@ -26,7 +26,7 @@ 6369A2751A9322E20015FC5C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; }; 6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; - C20055928615A6F8434E26B4 /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = "<group>"; }; /* End PBXFileReference section */ @@ -35,7 +35,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */, + 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -95,7 +95,7 @@ C4C2C5219053E079C9EFB930 /* Frameworks */ = { isa = PBXGroup; children = ( - C20055928615A6F8434E26B4 /* libPods-Sample.a */, + CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -129,7 +129,7 @@ 6369A2621A9322E20015FC5C /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0730; ORGANIZATIONNAME = gRPC; TargetAttributes = { 6369A2691A9322E20015FC5C = { @@ -260,6 +260,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -325,6 +326,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -336,6 +338,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/src/objective-c/examples/Sample/Sample/Info.plist b/src/objective-c/examples/Sample/Sample/Info.plist index 4436635ab4..2cdf09dc2f 100644 --- a/src/objective-c/examples/Sample/Sample/Info.plist +++ b/src/objective-c/examples/Sample/Sample/Info.plist @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> - <string>org.grpc.$(PRODUCT_NAME:rfc1034identifier)</string> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m index 433a8a2ba3..70244ee62d 100644 --- a/src/objective-c/examples/Sample/Sample/ViewController.m +++ b/src/objective-c/examples/Sample/Sample/ViewController.m @@ -66,9 +66,9 @@ // Same example call using the generic gRPC client library: - ProtoMethod *method = [[ProtoMethod alloc] initWithPackage:@"grpc.testing" - service:@"TestService" - method:@"UnaryCall"]; + GRPCProtoMethod *method = [[GRPCProtoMethod alloc] initWithPackage:@"grpc.testing" + service:@"TestService" + method:@"UnaryCall"]; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; diff --git a/src/objective-c/examples/SwiftSample/Info.plist b/src/objective-c/examples/SwiftSample/Info.plist index 10f0450b34..2cdf09dc2f 100644 --- a/src/objective-c/examples/SwiftSample/Info.plist +++ b/src/objective-c/examples/SwiftSample/Info.plist @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> - <string>io.grpc.$(PRODUCT_NAME:rfc1034identifier)</string> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> diff --git a/src/objective-c/examples/SwiftSample/Podfile b/src/objective-c/examples/SwiftSample/Podfile index f2df4a34a3..b08a346ae2 100644 --- a/src/objective-c/examples/SwiftSample/Podfile +++ b/src/objective-c/examples/SwiftSample/Podfile @@ -1,10 +1,48 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' -pod 'Protobuf', :path => "../../../../third_party/protobuf" -pod 'BoringSSL', :podspec => "../.." -pod 'gRPC', :path => "../../../.." -pod 'RemoteTest', :path => "../RemoteTestClient" +install! 'cocoapods', :deterministic_uuids => false + +use_frameworks! + +# Location of gRPC's repo root relative to this file. +GRPC_LOCAL_SRC = '../../../..' target 'SwiftSample' do + # Depend on the generated RemoteTestClient library + pod 'RemoteTest', :path => "../RemoteTestClient" + + # Use the local versions of Protobuf, BoringSSL, and gRPC. You don't need any of the following + # lines in your application. + pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + + pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf" + + pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" + + pod 'gRPC', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core', :path => GRPC_LOCAL_SRC + pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC + pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC +end + +# This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in +# your application. +pre_install do |installer| + # This is the gRPC-Core podspec object, as initialized by its podspec file. + grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec + + # Copied from gRPC-Core.podspec, except for the adjusted src_root: + src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" + grpc_core_spec.pod_target_xcconfig = { + 'GRPC_SRC_ROOT' => src_root, + 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', + 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', + # If we don't set these two settings, `include/grpc/support/time.h` and + # `src/core/lib/support/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the + # build. + 'USE_HEADERMAP' => 'NO', + 'ALWAYS_SEARCH_USER_PATHS' => 'NO', + } end diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj index 2a1b30f2cf..afc3da7116 100644 --- a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj @@ -7,11 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */; }; 633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC71B950B210007E424 /* AppDelegate.swift */; }; 633BFFCA1B950B210007E424 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC91B950B210007E424 /* ViewController.swift */; }; 633BFFCD1B950B210007E424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCB1B950B210007E424 /* Main.storyboard */; }; 633BFFCF1B950B210007E424 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCE1B950B210007E424 /* Images.xcassets */; }; - 92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -21,9 +21,8 @@ 633BFFC91B950B210007E424 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; }; 633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; - 6367AD231B951655007FD3A4 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; }; - 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SwiftSample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.debug.xcconfig"; sourceTree = "<group>"; }; + B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftSample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.release.xcconfig"; sourceTree = "<group>"; }; /* End PBXFileReference section */ @@ -32,7 +31,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */, + 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -74,7 +73,6 @@ 633BFFCB1B950B210007E424 /* Main.storyboard */, 633BFFCE1B950B210007E424 /* Images.xcassets */, 633BFFC51B950B210007E424 /* Supporting Files */, - 6367AD231B951655007FD3A4 /* Bridging-Header.h */, ); name = SwiftSample; sourceTree = SOURCE_ROOT; @@ -90,7 +88,7 @@ 9D63A7F6423989BA306810CA /* Frameworks */ = { isa = PBXGroup; children = ( - 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */, + B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -125,7 +123,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0730; ORGANIZATIONNAME = gRPC; TargetAttributes = { 633BFFC11B950B210007E424 = { @@ -256,6 +254,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -325,8 +324,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = ""; USER_HEADER_SEARCH_PATHS = ""; }; name = Debug; @@ -338,8 +338,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = ""; USER_HEADER_SEARCH_PATHS = ""; }; name = Release; diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift index 2a95d2de51..e7bab13762 100644 --- a/src/objective-c/examples/SwiftSample/ViewController.swift +++ b/src/objective-c/examples/SwiftSample/ViewController.swift @@ -33,6 +33,8 @@ import UIKit +import RemoteTest + class ViewController: UIViewController { override func viewDidLoad() { @@ -60,7 +62,7 @@ class ViewController: UIViewController { // Same but manipulating headers: - var RPC : ProtoRPC! // Needed to convince Swift to capture by reference (__block) + var RPC : GRPCProtoCall! // Needed to convince Swift to capture by reference (__block) RPC = service.RPCToUnaryCallWithRequest(request) { response, error in if let response = response { NSLog("2. Finished successfully with response:\n\(response)") @@ -79,7 +81,7 @@ class ViewController: UIViewController { // Same example call using the generic gRPC client library: - let method = ProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") + let method = GRPCProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") let requestsWriter = GRXWriter(value: request.data()) diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index a503f02059..494743d604 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -40,7 +40,6 @@ #import <GRPCClient/GRPCCall+Tests.h> #import <GRPCClient/GRPCCall+Cronet.h> #import <ProtoRPC/ProtoRPC.h> -#import <RemoteTest/Empty.pbobjc.h> #import <RemoteTest/Messages.pbobjc.h> #import <RemoteTest/Test.pbobjc.h> #import <RemoteTest/Test.pbrpc.h> @@ -110,12 +109,12 @@ static cronet_engine *cronetEngine = NULL; XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; - RMTEmpty *request = [RMTEmpty message]; + GPBEmpty *request = [GPBEmpty message]; - [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) { + [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); - id expectedResponse = [RMTEmpty message]; + id expectedResponse = [GPBEmpty message]; XCTAssertEqualObjects(response, expectedResponse); [expectation fulfill]; @@ -343,9 +342,9 @@ static cronet_engine *cronetEngine = NULL; __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC after closing connection"]; - RMTEmpty *request = [RMTEmpty message]; + GPBEmpty *request = [GPBEmpty message]; - [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) { + [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) { XCTAssertNil(error, @"First RPC finished with unexpected error: %@", error); #pragma clang diagnostic push @@ -353,7 +352,7 @@ static cronet_engine *cronetEngine = NULL; [GRPCCall closeOpenConnections]; #pragma clang diagnostic pop - [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) { + [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) { XCTAssertNil(error, @"Second RPC finished with unexpected error: %@", error); [expectation fulfill]; }]; diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 6d5f94cbda..17b9740d52 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -3,36 +3,65 @@ platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false -def shared_pods - pod 'Protobuf', :path => "../../../third_party/protobuf", :inhibit_warnings => true - pod 'BoringSSL', :podspec => "..", :inhibit_warnings => true - pod 'CronetFramework', :podspec => ".." - pod 'gRPC', :path => "../../.." - pod 'RemoteTest', :path => "RemoteTestClient" -end +# Location of gRPC's repo root relative to this file. +GRPC_LOCAL_SRC = '../../..' -target 'Tests' do - shared_pods -end +# Install the dependencies in the main target plus all test targets. +%w( + Tests + AllTests + RxLibraryUnitTests + InteropTestsRemote + InteropTestsLocalSSL + InteropTestsLocalCleartext +).each do |target_name| + target target_name do + pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true -target 'AllTests' do - shared_pods -end + pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" -target 'RxLibraryUnitTests' do - shared_pods -end + pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true + pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" -target 'InteropTestsRemote' do - shared_pods -end + pod 'gRPC', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core', :path => GRPC_LOCAL_SRC + pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC + pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC -target 'InteropTestsLocalSSL' do - shared_pods + pod 'RemoteTest', :path => "RemoteTestClient" + end end -target 'InteropTestsLocalCleartext' do - shared_pods +# gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's +# pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded +# and before they are installed in the user project. +# +# This podspec searches for the gRPC core library headers under "$(PODS_ROOT)/gRPC-Core", where +# Cocoapods normally places the downloaded sources. When doing local development of the libraries, +# though, Cocoapods just takes the sources from whatever directory was specified using `:path`, and +# doesn't copy them under $(PODS_ROOT). When using static libraries, one can sometimes rely on the +# symbolic links to the pods headers that Cocoapods creates under "$(PODS_ROOT)/Headers". But those +# aren't created when using dynamic frameworks. So our solution is to modify the podspec on the fly +# to point at the local directory where the sources are. +# +# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need. +pre_install do |installer| + # This is the gRPC-Core podspec object, as initialized by its podspec file. + grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec + + # Copied from gRPC-Core.podspec, except for the adjusted src_root: + src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" + grpc_core_spec.pod_target_xcconfig = { + 'GRPC_SRC_ROOT' => src_root, + 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', + 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', + # If we don't set these two settings, `include/grpc/support/time.h` and + # `src/core/lib/support/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the + # build. + 'USE_HEADERMAP' => 'NO', + 'ALWAYS_SEARCH_USER_PATHS' => 'NO', + } end post_install do |installer| @@ -40,9 +69,9 @@ post_install do |installer| target.build_configurations.each do |config| config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES' end - if target.name == 'gRPC' + if target.name == 'gRPC-Core' target.build_configurations.each do |config| - # TODO(zyc) Remove this setting after the issue is resolved + # TODO(zyc): Remove this setting after the issue is resolved # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void # function" warning config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' diff --git a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec index e1fd991038..53ba101913 100644 --- a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec +++ b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec @@ -11,25 +11,41 @@ Pod::Spec.new do |s| s.osx.deployment_target = '10.9' # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. + s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1" + + repo_root = '../../../..' + bin_dir = "#{repo_root}/bins/$CONFIG" + + protoc = "#{bin_dir}/protobuf/protoc" + well_known_types_dir = "#{repo_root}/third_party/protobuf/src" + plugin = "#{bin_dir}/grpc_objective_c_plugin" + s.prepare_command = <<-CMD - BINDIR=../../../../bins/$CONFIG - PROTOC=$BINDIR/protobuf/protoc - PLUGIN=$BINDIR/grpc_objective_c_plugin - $PROTOC --plugin=protoc-gen-grpc=$PLUGIN --objc_out=. --grpc_out=. *.proto + #{protoc} \ + --plugin=protoc-gen-grpc=#{plugin} \ + --objc_out=. \ + --grpc_out=. \ + -I . \ + -I #{well_known_types_dir} \ + *.proto CMD s.subspec "Messages" do |ms| ms.source_files = "*.pbobjc.{h,m}" ms.header_mappings_dir = "." ms.requires_arc = false - ms.dependency "Protobuf", "~> 3.0.0-alpha-4" + ms.dependency "Protobuf" + # This is needed by all pods that depend on Protobuf: + ms.pod_target_xcconfig = { + 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', + } end s.subspec "Services" do |ss| ss.source_files = "*.pbrpc.{h,m}" ss.header_mappings_dir = "." ss.requires_arc = true - ss.dependency "gRPC", "~> 0.12" + ss.dependency "gRPC-ProtoRPC" ss.dependency "#{s.name}/Messages" end end diff --git a/src/objective-c/tests/RemoteTestClient/empty.proto b/src/objective-c/tests/RemoteTestClient/empty.proto deleted file mode 100644 index a678048289..0000000000 --- a/src/objective-c/tests/RemoteTestClient/empty.proto +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2015, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package grpc.testing; - -option objc_class_prefix = "RMT"; - -// An empty message that you can re-use to avoid defining duplicated empty -// messages in your project. A typical example is to use it as argument or the -// return value of a service API. For instance: -// -// service Foo { -// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; -// }; -// -message Empty {} diff --git a/src/objective-c/tests/RemoteTestClient/test.proto b/src/objective-c/tests/RemoteTestClient/test.proto index 514c3b8095..5c359c5c12 100644 --- a/src/objective-c/tests/RemoteTestClient/test.proto +++ b/src/objective-c/tests/RemoteTestClient/test.proto @@ -31,7 +31,7 @@ // of unary/streaming requests/responses. syntax = "proto3"; -import "empty.proto"; +import "google/protobuf/empty.proto"; import "messages.proto"; package grpc.testing; @@ -42,7 +42,7 @@ option objc_class_prefix = "RMT"; // performance with various types of payload. service TestService { // One empty request followed by one empty response. - rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); + rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty); // One request followed by one response. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); diff --git a/src/objective-c/tests/build_example_test.sh b/src/objective-c/tests/build_example_test.sh index 5c3766b4c0..ae75941ec6 100755 --- a/src/objective-c/tests/build_example_test.sh +++ b/src/objective-c/tests/build_example_test.sh @@ -31,44 +31,33 @@ # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc -set -eo pipefail +set -evo pipefail cd `dirname $0` -BINDIR=`pwd`/../../../bins/$CONFIG -TMP_PATH=$PATH - -# If `protoc` is not found, add bins/$CONFIG/protobuf/protoc to the search path -hash protoc 2>/dev/null || TMP_PATH=$BINDIR/protobuf:$TMP_PATH - -# If `protoc-gen-objcgrpc` is not found, make a symlink from -# bins/$CONGIF/grpc_objective_c_plugin and add it to the search path -PATH=$TMP_PATH hash protoc-gen-objcgrpc 2>/dev/null || { - ln -sf $BINDIR/grpc_objective_c_plugin $BINDIR/protoc-gen-objcgrpc - TMP_PATH=$BINDIR:$TMP_PATH -} - SCHEME=HelloWorld \ EXAMPLE_PATH=examples/objective-c/helloworld \ - PATH=$TMP_PATH \ ./build_one_example.sh SCHEME=RouteGuideClient \ EXAMPLE_PATH=examples/objective-c/route_guide \ - PATH=$TMP_PATH \ ./build_one_example.sh SCHEME=AuthSample \ EXAMPLE_PATH=examples/objective-c/auth_sample \ - PATH=$TMP_PATH \ + ./build_one_example.sh + +rm -f ../examples/RemoteTestClient/*.{h,m} + +SCHEME=Sample \ + EXAMPLE_PATH=src/objective-c/examples/Sample \ ./build_one_example.sh SCHEME=Sample \ EXAMPLE_PATH=src/objective-c/examples/Sample \ - PATH=$TMP_PATH \ + FRAMEWORKS=YES \ ./build_one_example.sh SCHEME=SwiftSample \ EXAMPLE_PATH=src/objective-c/examples/SwiftSample \ - PATH=$TMP_PATH \ ./build_one_example.sh diff --git a/src/objective-c/tests/build_one_example.sh b/src/objective-c/tests/build_one_example.sh index 24fb8b7bab..9fef6582a3 100755 --- a/src/objective-c/tests/build_one_example.sh +++ b/src/objective-c/tests/build_one_example.sh @@ -31,7 +31,7 @@ # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc -set -e +set -ev # Params: # EXAMPLE_PATH - directory of the example @@ -54,7 +54,7 @@ pod install set -o pipefail XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail)' xcodebuild \ - clean build \ + build \ -workspace *.xcworkspace \ -scheme $SCHEME \ -destination name="iPhone 6" \ diff --git a/src/objective-c/tests/build_tests.sh b/src/objective-c/tests/build_tests.sh index 8547bfd3a8..bc5bc04494 100755 --- a/src/objective-c/tests/build_tests.sh +++ b/src/objective-c/tests/build_tests.sh @@ -44,26 +44,10 @@ hash xcodebuild 2>/dev/null || { exit 1 } -BINDIR=../../../bins/$CONFIG - -if [ ! -f $BINDIR/protobuf/protoc ]; then - hash protoc 2>/dev/null || { - echo >&2 "Can't find protoc. Make sure run_tests.py is making" \ - "grpc_objective_c_plugin before calling this script." - exit 1 - } - # When protoc is already installed, make doesn't compile one. Put a link - # there so the podspecs can do codegen using that path. - mkdir -p $BINDIR/protobuf - ln -s `which protoc` $BINDIR/protobuf/protoc -fi - -[ -f $BINDIR/interop_server ] || { - echo >&2 "Can't find the test server. Make sure run_tests.py is making" \ - "interop_server before calling this script. It needs to be done" \ - "before because pod install of gRPC renames some C gRPC files" \ - "and not the server's code references to them." - exit 1 -} +# clean the directory +rm -rf Pods +rm -rf Tests.xcworkspace +rm -f Podfile.lock +rm -f RemoteTestClient/*.{h,m} pod install diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index c4fc5644f2..a265149f48 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -31,13 +31,21 @@ # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc -set -e +set -ev cd $(dirname $0) # Run the tests server. -../../../bins/$CONFIG/interop_server --port=5050 & -../../../bins/$CONFIG/interop_server --port=5051 --use_tls & + +BINDIR=../../../bins/$CONFIG + +[ -f $BINDIR/interop_server ] || { + echo >&2 "Can't find the test server. Make sure run_tests.py is making" \ + "interop_server before calling this script." + exit 1 +} +$BINDIR/interop_server --port=5050 & +$BINDIR/interop_server --port=5051 --use_tls & # Kill them when this script exits. trap 'kill -9 `jobs -p`' EXIT diff --git a/src/php/README.md b/src/php/README.md index 6cc1ba4d46..8abedc40a3 100644 --- a/src/php/README.md +++ b/src/php/README.md @@ -5,7 +5,7 @@ This directory contains source code for PHP implementation of gRPC layered on sh #Status -Beta +GA ## Environment @@ -43,7 +43,7 @@ $ sudo mv phpunit-old.phar /usr/bin/phpunit Install the gRPC PHP extension ```sh -sudo pecl install grpc-beta +sudo pecl install grpc ``` This will compile and install the gRPC PHP extension into the standard PHP extension directory. You should be able to run the [unit tests](#unit-tests), with the PHP extension installed. @@ -75,7 +75,7 @@ $ sudo make install Install the gRPC PHP extension from PECL ```sh -$ sudo pecl install grpc-beta +$ sudo pecl install grpc ``` Or, compile from source @@ -148,7 +148,7 @@ Alternatively, you can download `protoc` binaries from [the protocol buffers Git You need to install `protoc-gen-php` to generate stub class `.php` files from service definition `.proto` files. ```sh -$ cd grpc/src/php/vendor/datto/protobuf-php # if you had run `composer install` in the previous step +$ cd grpc/src/php/vendor/stanley-cheung/protobuf-php # if you had run `composer install` in the previous step OR diff --git a/src/php/composer.json b/src/php/composer.json index 01674a25db..23bfcedbe6 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,20 +2,14 @@ "name": "grpc/grpc", "type": "library", "description": "gRPC library for PHP", - "version": "0.14.0", "keywords": ["rpc"], "homepage": "http://grpc.io", "license": "BSD-3-Clause", - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/stanley-cheung/Protobuf-PHP" - } - ], + "version": "1.0.0", "require": { "php": ">=5.5.0", - "datto/protobuf-php": "dev-master", - "google/auth": "v0.7" + "stanley-cheung/protobuf-php": "dev-master", + "google/auth": "v0.9" }, "autoload": { "psr-4": { diff --git a/src/php/ext/grpc/byte_buffer.c b/src/php/ext/grpc/byte_buffer.c index 2bf9e00305..3be1429f13 100644 --- a/src/php/ext/grpc/byte_buffer.c +++ b/src/php/ext/grpc/byte_buffer.c @@ -65,15 +65,13 @@ void byte_buffer_to_string(grpc_byte_buffer *buffer, char **out_string, *out_length = 0; return; } - size_t length = grpc_byte_buffer_length(buffer); + + gpr_slice slice = grpc_byte_buffer_reader_readall(&reader); + size_t length = GPR_SLICE_LENGTH(slice); char *string = ecalloc(length + 1, sizeof(char)); - size_t offset = 0; - gpr_slice next; - while (grpc_byte_buffer_reader_next(&reader, &next) != 0) { - memcpy(string + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next)); - offset += GPR_SLICE_LENGTH(next); - gpr_slice_unref(next); - } + memcpy(string, GPR_SLICE_START_PTR(slice), length); + gpr_slice_unref(slice); + *out_string = string; *out_length = length; } diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index 2cd45f10dc..bd1eccb01b 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -59,12 +59,15 @@ zend_class_entry *grpc_ce_call; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_call */ void free_wrapped_grpc_call(void *object TSRMLS_DC) { wrapped_grpc_call *call = (wrapped_grpc_call *)object; if (call->owned && call->wrapped != NULL) { grpc_call_destroy(call->wrapped); } + zend_object_std_dtor(&call->std TSRMLS_CC); efree(call); } @@ -203,6 +206,131 @@ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { return true; } +#else + +static zend_object_handlers call_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_call */ +static void free_wrapped_grpc_call(zend_object *object) { + wrapped_grpc_call *call = wrapped_grpc_call_from_obj(object); + if (call->owned && call->wrapped != NULL) { + grpc_call_destroy(call->wrapped); + } + zend_object_std_dtor(&call->std); +} + +/* Initializes an instance of wrapped_grpc_call to be associated with an + * object of a class specified by class_type */ +zend_object *create_wrapped_grpc_call(zend_class_entry *class_type) { + wrapped_grpc_call *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_call) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &call_ce_handlers; + return &intern->std; +} + +/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the + struct should be destroyed at the end of the object's lifecycle */ +void grpc_php_wrap_call(grpc_call *wrapped, bool owned, zval *call_object) { + object_init_ex(call_object, grpc_ce_call); + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(call_object); + call->wrapped = wrapped; + call->owned = owned; +} + +/* Creates and returns a PHP array object with the data in a + * grpc_metadata_array. Returns NULL on failure */ +void grpc_parse_metadata_array(grpc_metadata_array *metadata_array, + zval *array) { + int count = metadata_array->count; + grpc_metadata *elements = metadata_array->metadata; + int i; + zval *data; + HashTable *array_hash; + zval inner_array; + char *str_key; + char *str_val; + size_t key_len; + + array_init(array); + array_hash = HASH_OF(array); + grpc_metadata *elem; + for (i = 0; i < count; i++) { + elem = &elements[i]; + key_len = strlen(elem->key); + str_key = ecalloc(key_len + 1, sizeof(char)); + memcpy(str_key, elem->key, key_len); + str_val = ecalloc(elem->value_length + 1, sizeof(char)); + memcpy(str_val, elem->value, elem->value_length); + if ((data = zend_hash_str_find(array_hash, str_key, key_len)) != NULL) { + if (Z_TYPE_P(data) != IS_ARRAY) { + zend_throw_exception(zend_exception_get_default(), + "Metadata hash somehow contains wrong types.", + 1); + efree(str_key); + efree(str_val); + return; + } + add_next_index_stringl(data, str_val, elem->value_length); + } else { + array_init(&inner_array); + add_next_index_stringl(&inner_array, str_val, elem->value_length); + add_assoc_zval(array, str_key, &inner_array); + } + } +} + +/* Populates a grpc_metadata_array with the data in a PHP array object. + Returns true on success and false on failure */ +bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { + zval *inner_array; + zval *value; + HashTable *array_hash; + HashTable *inner_array_hash; + zend_string *key; + if (Z_TYPE_P(array) != IS_ARRAY) { + return false; + } + grpc_metadata_array_init(metadata); + array_hash = HASH_OF(array); + + ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, inner_array) { + if (key == NULL) { + return false; + } + if (Z_TYPE_P(inner_array) != IS_ARRAY) { + return false; + } + inner_array_hash = HASH_OF(inner_array); + metadata->capacity += zend_hash_num_elements(inner_array_hash); + } + ZEND_HASH_FOREACH_END(); + + metadata->metadata = gpr_malloc(metadata->capacity * sizeof(grpc_metadata)); + + ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, inner_array) { + if (key == NULL) { + return false; + } + inner_array_hash = HASH_OF(inner_array); + + ZEND_HASH_FOREACH_VAL(inner_array_hash, value) { + if (Z_TYPE_P(value) != IS_STRING) { + return false; + } + metadata->metadata[metadata->count].key = ZSTR_VAL(key); + metadata->metadata[metadata->count].value = Z_STRVAL_P(value); + metadata->metadata[metadata->count].value_length = Z_STRLEN_P(value); + metadata->count += 1; + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + return true; +} + +#endif + /** * Constructs a new instance of the Call class. * @param Channel $channel The channel to associate the call with. Must not be @@ -211,30 +339,38 @@ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { * @param Timeval $absolute_deadline The deadline for completing the call */ PHP_METHOD(Call, __construct) { - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); zval *channel_obj; char *method; - int method_len; zval *deadline_obj; char *host_override = NULL; +#if PHP_MAJOR_VERSION < 7 + int method_len; int host_override_len = 0; + wrapped_grpc_call *call = + (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + size_t method_len; + size_t host_override_len = 0; + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); +#endif + /* "OsO|s" == 1 Object, 1 string, 1 Object, 1 optional string */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", - &channel_obj, grpc_ce_channel, - &method, &method_len, - &deadline_obj, grpc_ce_timeval, - &host_override, &host_override_len) - == FAILURE) { - zend_throw_exception( - spl_ce_InvalidArgumentException, - "Call expects a Channel, a String, a Timeval and an optional String", - 1 TSRMLS_CC); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", &channel_obj, + grpc_ce_channel, &method, &method_len, + &deadline_obj, grpc_ce_timeval, &host_override, + &host_override_len) == FAILURE) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Call expects a Channel, a String, a Timeval and " + "an optional String", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object( channel_obj TSRMLS_CC); +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(channel_obj); +#endif if (channel->wrapped == NULL) { zend_throw_exception(spl_ce_InvalidArgumentException, "Call cannot be constructed from a closed Channel", @@ -242,12 +378,17 @@ PHP_METHOD(Call, __construct) { return; } add_property_zval(getThis(), "channel", channel_obj); +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *deadline = (wrapped_grpc_timeval *)zend_object_store_get_object( deadline_obj TSRMLS_CC); - call->wrapped = grpc_channel_create_call( - channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS, completion_queue, method, - host_override, deadline->wrapped, NULL); +#else + wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); +#endif + call->wrapped = + grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS, + completion_queue, method, host_override, + deadline->wrapped, NULL); call->owned = true; } @@ -257,22 +398,40 @@ PHP_METHOD(Call, __construct) { * @return object Object with results of all actions */ PHP_METHOD(Call, startBatch) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); - grpc_op ops[8]; - size_t op_num = 0; - zval *array; zval **value; zval **inner_value; - HashTable *array_hash; HashPosition array_pointer; - HashTable *status_hash; - HashTable *message_hash; zval **message_value; zval **message_flags; char *key; uint key_len; ulong index; + zval *result; + zval *recv_status; + MAKE_STD_ZVAL(result); + object_init(result); +#else + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); + zval *value; + zval *inner_value; + zval *message_value; + zval *message_flags; + zend_string *key; + zend_ulong index; + zval recv_status; + object_init(return_value); +#endif + + grpc_op ops[8]; + size_t op_num = 0; + zval *array; + HashTable *array_hash; + HashTable *status_hash; + HashTable *message_hash; + grpc_metadata_array metadata; grpc_metadata_array trailing_metadata; grpc_metadata_array recv_metadata; @@ -283,17 +442,16 @@ PHP_METHOD(Call, startBatch) { grpc_byte_buffer *message; int cancelled; grpc_call_error error; - zval *result; char *message_str; size_t message_len; - zval *recv_status; + + grpc_metadata_array_init(&metadata); grpc_metadata_array_init(&trailing_metadata); grpc_metadata_array_init(&recv_metadata); grpc_metadata_array_init(&recv_trailing_metadata); - MAKE_STD_ZVAL(result); - object_init(result); memset(ops, 0, sizeof(ops)); + /* "a" == 1 array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { @@ -301,6 +459,9 @@ PHP_METHOD(Call, startBatch) { "start_batch expects an array", 1 TSRMLS_CC); goto cleanup; } + +#if PHP_MAJOR_VERSION < 7 + array_hash = Z_ARRVAL_P(array); for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer); zend_hash_get_current_data_ex(array_hash, (void**)&value, @@ -313,124 +474,250 @@ PHP_METHOD(Call, startBatch) { goto cleanup; } switch(index) { - case GRPC_OP_SEND_INITIAL_METADATA: - if (!create_metadata_array(*value, &metadata)) { + case GRPC_OP_SEND_INITIAL_METADATA: + if (!create_metadata_array(*value, &metadata)) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Bad metadata value given", 1 TSRMLS_CC); + goto cleanup; + } + ops[op_num].data.send_initial_metadata.count = + metadata.count; + ops[op_num].data.send_initial_metadata.metadata = + metadata.metadata; + break; + case GRPC_OP_SEND_MESSAGE: + if (Z_TYPE_PP(value) != IS_ARRAY) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an array for send message", + 1 TSRMLS_CC); + goto cleanup; + } + message_hash = Z_ARRVAL_PP(value); + if (zend_hash_find(message_hash, "flags", sizeof("flags"), + (void **)&message_flags) == SUCCESS) { + if (Z_TYPE_PP(message_flags) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Bad metadata value given", 1 TSRMLS_CC); - goto cleanup; + "Expected an int for message flags", + 1 TSRMLS_CC); } - ops[op_num].data.send_initial_metadata.count = - metadata.count; - ops[op_num].data.send_initial_metadata.metadata = - metadata.metadata; - break; - case GRPC_OP_SEND_MESSAGE: - if (Z_TYPE_PP(value) != IS_ARRAY) { + ops[op_num].flags = Z_LVAL_PP(message_flags) & GRPC_WRITE_USED_MASK; + } + if (zend_hash_find(message_hash, "message", sizeof("message"), + (void **)&message_value) != SUCCESS || + Z_TYPE_PP(message_value) != IS_STRING) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected a string for send message", + 1 TSRMLS_CC); + goto cleanup; + } + ops[op_num].data.send_message = + string_to_byte_buffer(Z_STRVAL_PP(message_value), + Z_STRLEN_PP(message_value)); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + status_hash = Z_ARRVAL_PP(value); + if (zend_hash_find(status_hash, "metadata", sizeof("metadata"), + (void **)&inner_value) == SUCCESS) { + if (!create_metadata_array(*inner_value, &trailing_metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected an array for send message", + "Bad trailing metadata value given", 1 TSRMLS_CC); goto cleanup; } - message_hash = Z_ARRVAL_PP(value); - if (zend_hash_find(message_hash, "flags", sizeof("flags"), - (void **)&message_flags) == SUCCESS) { - if (Z_TYPE_PP(message_flags) != IS_LONG) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected an int for message flags", - 1 TSRMLS_CC); - } - ops[op_num].flags = Z_LVAL_PP(message_flags) & GRPC_WRITE_USED_MASK; + ops[op_num].data.send_status_from_server.trailing_metadata = + trailing_metadata.metadata; + ops[op_num].data.send_status_from_server.trailing_metadata_count = + trailing_metadata.count; + } + if (zend_hash_find(status_hash, "code", sizeof("code"), + (void**)&inner_value) == SUCCESS) { + if (Z_TYPE_PP(inner_value) != IS_LONG) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Status code must be an integer", + 1 TSRMLS_CC); + goto cleanup; } - if (zend_hash_find(message_hash, "message", sizeof("message"), - (void **)&message_value) != SUCCESS || - Z_TYPE_PP(message_value) != IS_STRING) { + ops[op_num].data.send_status_from_server.status = + Z_LVAL_PP(inner_value); + } else { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Integer status code is required", + 1 TSRMLS_CC); + goto cleanup; + } + if (zend_hash_find(status_hash, "details", sizeof("details"), + (void**)&inner_value) == SUCCESS) { + if (Z_TYPE_PP(inner_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected a string for send message", + "Status details must be a string", 1 TSRMLS_CC); goto cleanup; } - ops[op_num].data.send_message = - string_to_byte_buffer(Z_STRVAL_PP(message_value), - Z_STRLEN_PP(message_value)); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - status_hash = Z_ARRVAL_PP(value); - if (zend_hash_find(status_hash, "metadata", sizeof("metadata"), - (void **)&inner_value) == SUCCESS) { - if (!create_metadata_array(*inner_value, &trailing_metadata)) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Bad trailing metadata value given", - 1 TSRMLS_CC); - goto cleanup; - } - ops[op_num].data.send_status_from_server.trailing_metadata = - trailing_metadata.metadata; - ops[op_num].data.send_status_from_server.trailing_metadata_count = - trailing_metadata.count; + ops[op_num].data.send_status_from_server.status_details = + Z_STRVAL_PP(inner_value); + } else { + zend_throw_exception(spl_ce_InvalidArgumentException, + "String status details is required", + 1 TSRMLS_CC); + goto cleanup; + } + break; + case GRPC_OP_RECV_INITIAL_METADATA: + ops[op_num].data.recv_initial_metadata = &recv_metadata; + break; + case GRPC_OP_RECV_MESSAGE: + ops[op_num].data.recv_message = &message; + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + ops[op_num].data.recv_status_on_client.trailing_metadata = + &recv_trailing_metadata; + ops[op_num].data.recv_status_on_client.status = &status; + ops[op_num].data.recv_status_on_client.status_details = + &status_details; + ops[op_num].data.recv_status_on_client.status_details_capacity = + &status_details_capacity; + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + ops[op_num].data.recv_close_on_server.cancelled = &cancelled; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "Unrecognized key in batch", 1 TSRMLS_CC); + goto cleanup; + } + ops[op_num].op = (grpc_op_type)index; + ops[op_num].flags = 0; + ops[op_num].reserved = NULL; + op_num++; + } + +#else + +array_hash = HASH_OF(array); + ZEND_HASH_FOREACH_KEY_VAL(array_hash, index, key, value) { + if (key) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "batch keys must be integers", 1); + goto cleanup; + } + + switch(index) { + case GRPC_OP_SEND_INITIAL_METADATA: + if (!create_metadata_array(value, &metadata)) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Bad metadata value given", 1); + goto cleanup; + } + ops[op_num].data.send_initial_metadata.count = metadata.count; + ops[op_num].data.send_initial_metadata.metadata = metadata.metadata; + break; + case GRPC_OP_SEND_MESSAGE: + if (Z_TYPE_P(value) != IS_ARRAY) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an array for send message", 1); + goto cleanup; + } + message_hash = HASH_OF(value); + if ((message_flags = + zend_hash_str_find(message_hash, "flags", + sizeof("flags") - 1)) != NULL) { + if (Z_TYPE_P(message_flags) != IS_LONG) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an int for message flags", 1); + } + ops[op_num].flags = Z_LVAL_P(message_flags) & GRPC_WRITE_USED_MASK; + } + if ((message_value = zend_hash_str_find(message_hash, "message", + sizeof("message") - 1)) + == NULL || Z_TYPE_P(message_value) != IS_STRING) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected a string for send message", 1); + goto cleanup; + } + ops[op_num].data.send_message = + string_to_byte_buffer(Z_STRVAL_P(message_value), + Z_STRLEN_P(message_value)); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + status_hash = HASH_OF(value); + if ((inner_value = zend_hash_str_find(status_hash, "metadata", + sizeof("metadata") - 1)) + != NULL) { + if (!create_metadata_array(inner_value, &trailing_metadata)) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Bad trailing metadata value given", 1); + goto cleanup; } - if (zend_hash_find(status_hash, "code", sizeof("code"), - (void**)&inner_value) == SUCCESS) { - if (Z_TYPE_PP(inner_value) != IS_LONG) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Status code must be an integer", - 1 TSRMLS_CC); - goto cleanup; - } - ops[op_num].data.send_status_from_server.status = - Z_LVAL_PP(inner_value); - } else { + ops[op_num].data.send_status_from_server.trailing_metadata = + trailing_metadata.metadata; + ops[op_num].data.send_status_from_server.trailing_metadata_count = + trailing_metadata.count; + } + if ((inner_value = zend_hash_str_find(status_hash, "code", + sizeof("code") - 1)) != NULL) { + if (Z_TYPE_P(inner_value) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Integer status code is required", - 1 TSRMLS_CC); + "Status code must be an integer", 1); goto cleanup; } - if (zend_hash_find(status_hash, "details", sizeof("details"), - (void**)&inner_value) == SUCCESS) { - if (Z_TYPE_PP(inner_value) != IS_STRING) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Status details must be a string", - 1 TSRMLS_CC); - goto cleanup; - } - ops[op_num].data.send_status_from_server.status_details = - Z_STRVAL_PP(inner_value); - } else { + ops[op_num].data.send_status_from_server.status = + Z_LVAL_P(inner_value); + } else { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Integer status code is required", 1); + goto cleanup; + } + if ((inner_value = zend_hash_str_find(status_hash, "details", + sizeof("details") - 1)) != NULL) { + if (Z_TYPE_P(inner_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, - "String status details is required", - 1 TSRMLS_CC); + "Status details must be a string", 1); goto cleanup; } - break; - case GRPC_OP_RECV_INITIAL_METADATA: - ops[op_num].data.recv_initial_metadata = &recv_metadata; - break; - case GRPC_OP_RECV_MESSAGE: - ops[op_num].data.recv_message = &message; - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - ops[op_num].data.recv_status_on_client.trailing_metadata = - &recv_trailing_metadata; - ops[op_num].data.recv_status_on_client.status = &status; - ops[op_num].data.recv_status_on_client.status_details = - &status_details; - ops[op_num].data.recv_status_on_client.status_details_capacity = - &status_details_capacity; - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - ops[op_num].data.recv_close_on_server.cancelled = &cancelled; - break; - default: + ops[op_num].data.send_status_from_server.status_details = + Z_STRVAL_P(inner_value); + } else { zend_throw_exception(spl_ce_InvalidArgumentException, - "Unrecognized key in batch", 1 TSRMLS_CC); + "String status details is required", 1); goto cleanup; + } + break; + case GRPC_OP_RECV_INITIAL_METADATA: + ops[op_num].data.recv_initial_metadata = &recv_metadata; + break; + case GRPC_OP_RECV_MESSAGE: + ops[op_num].data.recv_message = &message; + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + ops[op_num].data.recv_status_on_client.trailing_metadata = + &recv_trailing_metadata; + ops[op_num].data.recv_status_on_client.status = &status; + ops[op_num].data.recv_status_on_client.status_details = + &status_details; + ops[op_num].data.recv_status_on_client.status_details_capacity = + &status_details_capacity; + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + ops[op_num].data.recv_close_on_server.cancelled = &cancelled; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "Unrecognized key in batch", 1); + goto cleanup; } ops[op_num].op = (grpc_op_type)index; ops[op_num].flags = 0; ops[op_num].reserved = NULL; op_num++; } + ZEND_HASH_FOREACH_END(); + +#endif + error = grpc_call_start_batch(call->wrapped, ops, op_num, call->wrapped, NULL); if (error != GRPC_CALL_OK) { @@ -441,52 +728,98 @@ PHP_METHOD(Call, startBatch) { } grpc_completion_queue_pluck(completion_queue, call->wrapped, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +#if PHP_MAJOR_VERSION < 7 for (int i = 0; i < op_num; i++) { switch(ops[i].op) { - case GRPC_OP_SEND_INITIAL_METADATA: - add_property_bool(result, "send_metadata", true); - break; - case GRPC_OP_SEND_MESSAGE: - add_property_bool(result, "send_message", true); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - add_property_bool(result, "send_close", true); - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - add_property_bool(result, "send_status", true); - break; - case GRPC_OP_RECV_INITIAL_METADATA: - array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC); - add_property_zval(result, "metadata", array); - Z_DELREF_P(array); - break; - case GRPC_OP_RECV_MESSAGE: - byte_buffer_to_string(message, &message_str, &message_len); - if (message_str == NULL) { - add_property_null(result, "message"); - } else { - add_property_stringl(result, "message", message_str, message_len, - false); - } - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - MAKE_STD_ZVAL(recv_status); - object_init(recv_status); - array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC); - add_property_zval(recv_status, "metadata", array); - Z_DELREF_P(array); - add_property_long(recv_status, "code", status); - add_property_string(recv_status, "details", status_details, true); - add_property_zval(result, "status", recv_status); - Z_DELREF_P(recv_status); - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - add_property_bool(result, "cancelled", cancelled); - break; - default: - break; + case GRPC_OP_SEND_INITIAL_METADATA: + add_property_bool(result, "send_metadata", true); + break; + case GRPC_OP_SEND_MESSAGE: + add_property_bool(result, "send_message", true); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + add_property_bool(result, "send_close", true); + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + add_property_bool(result, "send_status", true); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC); + add_property_zval(result, "metadata", array); + Z_DELREF_P(array); + break; + case GRPC_OP_RECV_MESSAGE: + byte_buffer_to_string(message, &message_str, &message_len); + if (message_str == NULL) { + add_property_null(result, "message"); + } else { + add_property_stringl(result, "message", message_str, message_len, + false); + } + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + MAKE_STD_ZVAL(recv_status); + object_init(recv_status); + array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC); + add_property_zval(recv_status, "metadata", array); + Z_DELREF_P(array); + add_property_long(recv_status, "code", status); + add_property_string(recv_status, "details", status_details, true); + add_property_zval(result, "status", recv_status); + Z_DELREF_P(recv_status); + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + add_property_bool(result, "cancelled", cancelled); + break; + default: + break; + } + } +#else + for (int i = 0; i < op_num; i++) { + switch(ops[i].op) { + case GRPC_OP_SEND_INITIAL_METADATA: + add_property_bool(return_value, "send_metadata", true); + break; + case GRPC_OP_SEND_MESSAGE: + add_property_bool(return_value, "send_message", true); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + add_property_bool(return_value, "send_close", true); + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + add_property_bool(return_value, "send_status", true); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + grpc_parse_metadata_array(&recv_metadata, array); + add_property_zval(return_value, "metadata", array); + break; + case GRPC_OP_RECV_MESSAGE: + byte_buffer_to_string(message, &message_str, &message_len); + if (message_str == NULL) { + add_property_null(return_value, "message"); + } else { + add_property_stringl(return_value, "message", message_str, + message_len); + } + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + object_init(&recv_status); + grpc_parse_metadata_array(&recv_trailing_metadata, array); + add_property_zval(&recv_status, "metadata", array); + add_property_long(&recv_status, "code", status); + add_property_string(&recv_status, "details", status_details); + add_property_zval(return_value, "status", &recv_status); + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + add_property_bool(return_value, "cancelled", cancelled); + break; + default: + break; } } +#endif + cleanup: grpc_metadata_array_destroy(&metadata); grpc_metadata_array_destroy(&trailing_metadata); @@ -503,7 +836,11 @@ cleanup: grpc_byte_buffer_destroy(message); } } +#if PHP_MAJOR_VERSION < 7 RETURN_DESTROY_ZVAL(result); +#else + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -511,9 +848,14 @@ cleanup: * @return string The URI of the endpoint */ PHP_METHOD(Call, getPeer) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_STRING(grpc_call_get_peer(call->wrapped), 1); +#else + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); + RETURN_STRING(grpc_call_get_peer(call->wrapped)); +#endif } /** @@ -521,8 +863,12 @@ PHP_METHOD(Call, getPeer) { * has not already ended with another status. */ PHP_METHOD(Call, cancel) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); +#endif grpc_call_cancel(call->wrapped, NULL); } @@ -543,12 +889,17 @@ PHP_METHOD(Call, setCredentials) { return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call_credentials *creds = (wrapped_grpc_call_credentials *)zend_object_store_get_object( creds_obj TSRMLS_CC); - wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_call_credentials *creds = + Z_WRAPPED_GRPC_CALL_CREDS_P(creds_obj); + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); +#endif grpc_call_error error = GRPC_CALL_ERROR; error = grpc_call_set_credentials(call->wrapped, creds->wrapped); @@ -556,16 +907,23 @@ PHP_METHOD(Call, setCredentials) { } static zend_function_entry call_methods[] = { - PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC) - PHP_FE_END}; + PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; void grpc_init_call(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Call", call_methods); ce.create_object = create_wrapped_grpc_call; grpc_ce_call = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&call_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + call_ce_handlers.offset = XtOffsetOf(wrapped_grpc_call, std); + call_ce_handlers.free_obj = free_wrapped_grpc_call; +#endif } diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h index 36c5f2d272..9fc52d7820 100644 --- a/src/php/ext/grpc/call.h +++ b/src/php/ext/grpc/call.h @@ -48,17 +48,15 @@ /* Class entry for the Call PHP class */ extern zend_class_entry *grpc_ce_call; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_call that can be associated with a PHP object */ typedef struct wrapped_grpc_call { zend_object std; - bool owned; grpc_call *wrapped; } wrapped_grpc_call; -/* Initializes the Call PHP class */ -void grpc_init_call(TSRMLS_D); - /* Creates a Call object that wraps the given grpc_call struct */ zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC); @@ -66,6 +64,36 @@ zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC); * call metadata */ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC); +#else + +/* Wrapper struct for grpc_call that can be associated with a PHP object */ +typedef struct wrapped_grpc_call { + bool owned; + grpc_call *wrapped; + zend_object std; +} wrapped_grpc_call; + +static inline wrapped_grpc_call +*wrapped_grpc_call_from_obj(zend_object *obj) { + return (wrapped_grpc_call*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_call, std)); +} + +#define Z_WRAPPED_GRPC_CALL_P(zv) wrapped_grpc_call_from_obj(Z_OBJ_P((zv))) + +/* Creates a Call object that wraps the given grpc_call struct */ +void grpc_php_wrap_call(grpc_call *wrapped, bool owned, zval *call_object); + +/* Creates and returns a PHP associative array of metadata from a C array of + * call metadata */ +void grpc_parse_metadata_array(grpc_metadata_array *metadata_array, + zval *array); + +#endif /* PHP_MAJOR_VERSION */ + +/* Initializes the Call PHP class */ +void grpc_init_call(TSRMLS_D); + /* Populates a grpc_metadata_array with the data in a PHP array object. Returns true on success and false on failure */ bool create_metadata_array(zval *array, grpc_metadata_array *metadata); diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c index ec0e6b9181..70aaffb848 100644 --- a/src/php/ext/grpc/call_credentials.c +++ b/src/php/ext/grpc/call_credentials.c @@ -53,6 +53,8 @@ zend_class_entry *grpc_ce_call_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_call_credentials */ void free_wrapped_grpc_call_credentials(void *object TSRMLS_DC) { wrapped_grpc_call_credentials *creds = @@ -60,6 +62,7 @@ void free_wrapped_grpc_call_credentials(void *object TSRMLS_DC) { if (creds->wrapped != NULL) { grpc_call_credentials_release(creds->wrapped); } + zend_object_std_dtor(&creds->std TSRMLS_CC); efree(creds); } @@ -94,6 +97,43 @@ zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped TSRMLS_DC) { return credentials_object; } +#else + +static zend_object_handlers call_credentials_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_call_credentials */ +static void free_wrapped_grpc_call_credentials(zend_object *object) { + wrapped_grpc_call_credentials *creds = + wrapped_grpc_call_creds_from_obj(object); + if (creds->wrapped != NULL) { + grpc_call_credentials_release(creds->wrapped); + } + zend_object_std_dtor(&creds->std); +} + +/* Initializes an instance of wrapped_grpc_call_credentials to be + * associated with an object of a class specified by class_type */ +zend_object *create_wrapped_grpc_call_credentials(zend_class_entry + *class_type) { + wrapped_grpc_call_credentials *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_call_credentials) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &call_credentials_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped, + zval *credentials_object) { + object_init_ex(credentials_object, grpc_ce_call_credentials); + wrapped_grpc_call_credentials *credentials = + Z_WRAPPED_GRPC_CALL_CREDS_P(credentials_object); + credentials->wrapped = wrapped; +} + +#endif + /** * Create composite credentials from two existing credentials. * @param CallCredentials cred1 The first credential @@ -113,6 +153,7 @@ PHP_METHOD(CallCredentials, createComposite) { 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call_credentials *cred1 = (wrapped_grpc_call_credentials *)zend_object_store_get_object( cred1_obj TSRMLS_CC); @@ -124,6 +165,17 @@ PHP_METHOD(CallCredentials, createComposite) { NULL); zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + wrapped_grpc_call_credentials *cred1 = + Z_WRAPPED_GRPC_CALL_CREDS_P(cred1_obj); + wrapped_grpc_call_credentials *cred2 = + Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); + grpc_call_credentials *creds = + grpc_composite_call_credentials_create(cred1->wrapped, + cred2->wrapped, NULL); + grpc_php_wrap_call_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -141,13 +193,10 @@ PHP_METHOD(CallCredentials, createFromPlugin) { memset(fci_cache, 0, sizeof(zend_fcall_info_cache)); /* "f" == 1 function */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", fci, - fci_cache, - fci->params, - fci->param_count) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f*", fci, fci_cache, + fci->params, fci->param_count) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, - "createFromPlugin expects 1 callback", - 1 TSRMLS_CC); + "createFromPlugin expects 1 callback", 1 TSRMLS_CC); return; } @@ -165,10 +214,15 @@ PHP_METHOD(CallCredentials, createFromPlugin) { plugin.state = (void *)state; plugin.type = ""; - grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin( - plugin, NULL); + grpc_call_credentials *creds = + grpc_metadata_credentials_create_from_plugin(plugin, NULL); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_call_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /* Callback function for plugin creds API */ @@ -181,6 +235,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context, /* prepare to call the user callback function with info from the * grpc_auth_metadata_context */ +#if PHP_MAJOR_VERSION < 7 zval **params[1]; zval *arg; zval *retval; @@ -192,21 +247,41 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context, state->fci->param_count = 1; state->fci->params = params; state->fci->retval_ptr_ptr = &retval; +#else + zval arg; + zval retval; + object_init(&arg); + add_property_string(&arg, "service_url", context.service_url); + add_property_string(&arg, "method_name", context.method_name); + state->fci->param_count = 1; + state->fci->params = &arg; + state->fci->retval = &retval; +#endif /* call the user callback function */ zend_call_function(state->fci, state->fci_cache TSRMLS_CC); +#if PHP_MAJOR_VERSION < 7 if (Z_TYPE_P(retval) != IS_ARRAY) { +#else + if (Z_TYPE_P(&retval) != IS_ARRAY) { +#endif zend_throw_exception(spl_ce_InvalidArgumentException, "plugin callback must return metadata array", 1 TSRMLS_CC); + return; } grpc_metadata_array metadata; +#if PHP_MAJOR_VERSION < 7 if (!create_metadata_array(retval, &metadata)) { +#else + if (!create_metadata_array(&retval, &metadata)) { +#endif zend_throw_exception(spl_ce_InvalidArgumentException, "invalid metadata", 1 TSRMLS_CC); grpc_metadata_array_destroy(&metadata); + return; } /* TODO: handle error */ @@ -229,11 +304,21 @@ static zend_function_entry call_credentials_methods[] = { ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(CallCredentials, createFromPlugin, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_FE_END}; + PHP_FE_END +}; void grpc_init_call_credentials(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\CallCredentials", call_credentials_methods); ce.create_object = create_wrapped_grpc_call_credentials; grpc_ce_call_credentials = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&call_credentials_ce_handlers, + zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + call_credentials_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_call_credentials, std); + call_credentials_ce_handlers.free_obj = + free_wrapped_grpc_call_credentials; +#endif } diff --git a/src/php/ext/grpc/call_credentials.h b/src/php/ext/grpc/call_credentials.h index d2f6a92449..e05e14698b 100755 --- a/src/php/ext/grpc/call_credentials.h +++ b/src/php/ext/grpc/call_credentials.h @@ -49,14 +49,37 @@ /* Class entry for the CallCredentials PHP class */ extern zend_class_entry *grpc_ce_call_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_call_credentials that can be associated * with a PHP object */ typedef struct wrapped_grpc_call_credentials { zend_object std; + grpc_call_credentials *wrapped; +} wrapped_grpc_call_credentials; +#else + +/* Wrapper struct for grpc_call_credentials that can be associated + * with a PHP object */ +typedef struct wrapped_grpc_call_credentials { grpc_call_credentials *wrapped; + zend_object std; } wrapped_grpc_call_credentials; +static inline wrapped_grpc_call_credentials +*wrapped_grpc_call_creds_from_obj(zend_object *obj) { + return + (wrapped_grpc_call_credentials*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_call_credentials, + std)); +} + +#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \ + wrapped_grpc_call_creds_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Struct to hold callback function for plugin creds API */ typedef struct plugin_state { zend_fcall_info *fci; diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index 9f0431908f..6737e340f9 100644 --- a/src/php/ext/grpc/channel.c +++ b/src/php/ext/grpc/channel.c @@ -48,7 +48,6 @@ #include <stdbool.h> #include <grpc/grpc.h> -#include <grpc/support/log.h> #include <grpc/grpc_security.h> #include "completion_queue.h" @@ -58,12 +57,15 @@ zend_class_entry *grpc_ce_channel; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_channel */ void free_wrapped_grpc_channel(void *object TSRMLS_DC) { wrapped_grpc_channel *channel = (wrapped_grpc_channel *)object; if (channel->wrapped != NULL) { grpc_channel_destroy(channel->wrapped); } + zend_object_std_dtor(&channel->std TSRMLS_CC); efree(channel); } @@ -84,7 +86,8 @@ zend_object_value create_wrapped_grpc_channel(zend_class_entry *class_type return retval; } -void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC) { +void php_grpc_read_args_array(zval *args_array, + grpc_channel_args *args TSRMLS_DC) { HashTable *array_hash; HashPosition array_pointer; int args_index; @@ -108,23 +111,88 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_D } args->args[args_index].key = key; switch (Z_TYPE_P(*data)) { - case IS_LONG: - args->args[args_index].value.integer = (int)Z_LVAL_P(*data); - args->args[args_index].type = GRPC_ARG_INTEGER; - break; - case IS_STRING: - args->args[args_index].value.string = Z_STRVAL_P(*data); - args->args[args_index].type = GRPC_ARG_STRING; - break; - default: - zend_throw_exception(spl_ce_InvalidArgumentException, - "args values must be int or string", 1 TSRMLS_CC); - return; + case IS_LONG: + args->args[args_index].value.integer = (int)Z_LVAL_P(*data); + args->args[args_index].type = GRPC_ARG_INTEGER; + break; + case IS_STRING: + args->args[args_index].value.string = Z_STRVAL_P(*data); + args->args[args_index].type = GRPC_ARG_STRING; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "args values must be int or string", 1 TSRMLS_CC); + return; } args_index++; } } +#else + +static zend_object_handlers channel_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_channel */ +static void free_wrapped_grpc_channel(zend_object *object) { + wrapped_grpc_channel *channel = wrapped_grpc_channel_from_obj(object); + if (channel->wrapped != NULL) { + grpc_channel_destroy(channel->wrapped); + } + zend_object_std_dtor(&channel->std); +} + +/* Initializes an instance of wrapped_grpc_channel to be associated with an + * object of a class specified by class_type */ +zend_object *create_wrapped_grpc_channel(zend_class_entry *class_type) { + wrapped_grpc_channel *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_channel) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &channel_ce_handlers; + return &intern->std; +} + +void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) { + HashTable *array_hash; + int args_index; + zval *data; + zend_string *key; + array_hash = HASH_OF(args_array); + if (!array_hash) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "array_hash is NULL", 1); + return; + } + args->num_args = zend_hash_num_elements(array_hash); + args->args = ecalloc(args->num_args, sizeof(grpc_arg)); + args_index = 0; + ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, data) { + if (key == NULL) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "args keys must be strings", 1); + } + args->args[args_index].key = ZSTR_VAL(key); + switch (Z_TYPE_P(data)) { + case IS_LONG: + args->args[args_index].value.integer = (int)Z_LVAL_P(data); + args->args[args_index].type = GRPC_ARG_INTEGER; + break; + case IS_STRING: + args->args[args_index].value.string = Z_STRVAL_P(data); + args->args[args_index].type = GRPC_ARG_STRING; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "args values must be int or string", 1); + return; + } + args_index++; + } ZEND_HASH_FOREACH_END(); +} + +#endif + /** * Construct an instance of the Channel class. If the $args array contains a * "credentials" key mapping to a ChannelCredentials object, a secure channel @@ -133,16 +201,23 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_D * @param array $args The arguments to pass to the Channel (optional) */ PHP_METHOD(Channel, __construct) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object( getThis() TSRMLS_CC); - char *target; + zval **creds_obj = NULL; int target_length; +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); + zval *creds_obj = NULL; + size_t target_length; +#endif + char *target; zval *args_array = NULL; grpc_channel_args args; HashTable *array_hash; - zval **creds_obj = NULL; wrapped_grpc_channel_credentials *creds = NULL; + /* "sa" == 1 string, 1 array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target, &target_length, &args_array) == FAILURE) { @@ -150,6 +225,7 @@ PHP_METHOD(Channel, __construct) { "Channel expects a string and an array", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 array_hash = Z_ARRVAL_P(args_array); if (zend_hash_find(array_hash, "credentials", sizeof("credentials"), (void **)&creds_obj) == SUCCESS) { @@ -168,11 +244,28 @@ PHP_METHOD(Channel, __construct) { zend_hash_del(array_hash, "credentials", 12); } } +#else + array_hash = HASH_OF(args_array); + if ((creds_obj = zend_hash_str_find(array_hash, "credentials", + sizeof("credentials") - 1)) != NULL) { + if (Z_TYPE_P(creds_obj) == IS_NULL) { + creds = NULL; + zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); + } else if (Z_OBJ_P(creds_obj)->ce != grpc_ce_channel_credentials) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "credentials must be a ChannelCredentials object", + 1); + return; + } else { + creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj); + zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); + } + } +#endif php_grpc_read_args_array(args_array, &args TSRMLS_CC); if (creds == NULL) { channel->wrapped = grpc_insecure_channel_create(target, &args, NULL); } else { - gpr_log(GPR_DEBUG, "Initialized secure channel"); channel->wrapped = grpc_secure_channel_create(creds->wrapped, target, &args, NULL); } @@ -184,9 +277,14 @@ PHP_METHOD(Channel, __construct) { * @return string The URI of the endpoint */ PHP_METHOD(Channel, getTarget) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); + (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1); +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); + RETURN_STRING(grpc_channel_get_target(channel->wrapped)); +#endif } /** @@ -195,12 +293,17 @@ PHP_METHOD(Channel, getTarget) { * @return long The grpc connectivity state */ PHP_METHOD(Channel, getConnectivityState) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); - bool try_to_connect; +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); +#endif + bool try_to_connect = false; + /* "|b" == 1 optional bool */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect) + == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "getConnectivityState expects a bool", 1 TSRMLS_CC); return; @@ -217,10 +320,16 @@ PHP_METHOD(Channel, getConnectivityState) { * before deadline */ PHP_METHOD(Channel, watchConnectivityState) { +#if PHP_MAJOR_VERSION < 7 + long last_state; wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); - long last_state; +#else + zend_long last_state; + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); +#endif zval *deadline_obj; + /* "lO" == 1 long 1 object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO", &last_state, &deadline_obj, grpc_ce_timeval) == FAILURE) { @@ -230,15 +339,20 @@ PHP_METHOD(Channel, watchConnectivityState) { return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *deadline = (wrapped_grpc_timeval *)zend_object_store_get_object( deadline_obj TSRMLS_CC); - grpc_channel_watch_connectivity_state( - channel->wrapped, (grpc_connectivity_state)last_state, - deadline->wrapped, completion_queue, NULL); - grpc_event event = grpc_completion_queue_pluck( - completion_queue, NULL, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +#else + wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); +#endif + grpc_channel_watch_connectivity_state(channel->wrapped, + (grpc_connectivity_state)last_state, + deadline->wrapped, completion_queue, + NULL); + grpc_event event = + grpc_completion_queue_pluck(completion_queue, NULL, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); RETURN_BOOL(event.success); } @@ -246,8 +360,12 @@ PHP_METHOD(Channel, watchConnectivityState) { * Close the channel */ PHP_METHOD(Channel, close) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); + (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); +#endif if (channel->wrapped != NULL) { grpc_channel_destroy(channel->wrapped); channel->wrapped = NULL; @@ -255,16 +373,24 @@ PHP_METHOD(Channel, close) { } static zend_function_entry channel_methods[] = { - PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC) - PHP_FE_END}; + PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; void grpc_init_channel(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods); ce.create_object = create_wrapped_grpc_channel; grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&channel_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + channel_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_channel, std); + channel_ce_handlers.free_obj = free_wrapped_grpc_channel; +#endif } diff --git a/src/php/ext/grpc/channel.h b/src/php/ext/grpc/channel.h index cc5823ee7f..ea5efeaf86 100755 --- a/src/php/ext/grpc/channel.h +++ b/src/php/ext/grpc/channel.h @@ -48,17 +48,38 @@ /* Class entry for the PHP Channel class */ extern zend_class_entry *grpc_ce_channel; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_channel that can be associated with a PHP object */ typedef struct wrapped_grpc_channel { zend_object std; + grpc_channel *wrapped; +} wrapped_grpc_channel; +#else + +/* Wrapper struct for grpc_channel that can be associated with a PHP object */ +typedef struct wrapped_grpc_channel { grpc_channel *wrapped; + zend_object std; } wrapped_grpc_channel; +static inline wrapped_grpc_channel +*wrapped_grpc_channel_from_obj(zend_object *obj) { + return (wrapped_grpc_channel*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_channel, std)); +} + +#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \ + wrapped_grpc_channel_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the Channel class */ void grpc_init_channel(TSRMLS_D); /* Iterates through a PHP array and populates args with the contents */ -void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC); +void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args + TSRMLS_DC); #endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */ diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c index b76fb105f3..16ba0368eb 100644 --- a/src/php/ext/grpc/channel_credentials.c +++ b/src/php/ext/grpc/channel_credentials.c @@ -52,7 +52,6 @@ #include <grpc/grpc_security.h> zend_class_entry *grpc_ce_channel_credentials; - static char *default_pem_root_certs = NULL; static grpc_ssl_roots_override_result get_ssl_roots_override( @@ -64,6 +63,8 @@ static grpc_ssl_roots_override_result get_ssl_roots_override( return GRPC_SSL_ROOTS_OVERRIDE_OK; } +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_channel_credentials */ void free_wrapped_grpc_channel_credentials(void *object TSRMLS_DC) { wrapped_grpc_channel_credentials *creds = @@ -71,6 +72,7 @@ void free_wrapped_grpc_channel_credentials(void *object TSRMLS_DC) { if (creds->wrapped != NULL) { grpc_channel_credentials_release(creds->wrapped); } + zend_object_std_dtor(&creds->std TSRMLS_CC); efree(creds); } @@ -94,7 +96,8 @@ zend_object_value create_wrapped_grpc_channel_credentials( return retval; } -zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS_DC) { +zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials + *wrapped TSRMLS_DC) { zval *credentials_object; MAKE_STD_ZVAL(credentials_object); object_init_ex(credentials_object, grpc_ce_channel_credentials); @@ -105,6 +108,43 @@ zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS return credentials_object; } +#else + +static zend_object_handlers channel_credentials_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_channel_credentials */ +static void free_wrapped_grpc_channel_credentials(zend_object *object) { + wrapped_grpc_channel_credentials *creds = + wrapped_grpc_channel_creds_from_obj(object); + if (creds->wrapped != NULL) { + grpc_channel_credentials_release(creds->wrapped); + } + zend_object_std_dtor(&creds->std); +} + +/* Initializes an instance of wrapped_grpc_channel_credentials to be + * associated with an object of a class specified by class_type */ +zend_object *create_wrapped_grpc_channel_credentials(zend_class_entry + *class_type) { + wrapped_grpc_channel_credentials *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_channel_credentials) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &channel_credentials_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped, + zval *credentials_object) { + object_init_ex(credentials_object, grpc_ce_channel_credentials); + wrapped_grpc_channel_credentials *credentials = + Z_WRAPPED_GRPC_CHANNEL_CREDS_P(credentials_object); + credentials->wrapped = wrapped; +} + +#endif + /** * Set default roots pem. * @param string pem_roots PEM encoding of the server root certificates @@ -112,7 +152,13 @@ zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS */ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { char *pem_roots; +#if PHP_MAJOR_VERSION < 7 int pem_roots_length; +#else + size_t pem_roots_length; +#endif + + /* "s" == 1 string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pem_roots, &pem_roots_length) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, @@ -129,8 +175,13 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { */ PHP_METHOD(ChannelCredentials, createDefault) { grpc_channel_credentials *creds = grpc_google_default_credentials_create(); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_channel_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -146,11 +197,15 @@ PHP_METHOD(ChannelCredentials, createSsl) { char *pem_root_certs = NULL; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; +#if PHP_MAJOR_VERSION < 7 int root_certs_length = 0, private_key_length = 0, cert_chain_length = 0; +#else + size_t root_certs_length = 0, private_key_length = 0, cert_chain_length = 0; +#endif pem_key_cert_pair.private_key = pem_key_cert_pair.cert_chain = NULL; - /* "|s!s!s! == 3 optional nullable strings */ + /* "|s!s!s!" == 3 optional nullable strings */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!", &pem_root_certs, &root_certs_length, &pem_key_cert_pair.private_key, @@ -164,8 +219,13 @@ PHP_METHOD(ChannelCredentials, createSsl) { grpc_channel_credentials *creds = grpc_ssl_credentials_create( pem_root_certs, pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_channel_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -178,7 +238,7 @@ PHP_METHOD(ChannelCredentials, createComposite) { zval *cred1_obj; zval *cred2_obj; - /* "OO" == 3 Objects */ + /* "OO" == 2 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj, grpc_ce_channel_credentials, &cred2_obj, grpc_ce_call_credentials) == FAILURE) { @@ -186,6 +246,7 @@ PHP_METHOD(ChannelCredentials, createComposite) { "createComposite expects 2 Credentials", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel_credentials *cred1 = (wrapped_grpc_channel_credentials *)zend_object_store_get_object( cred1_obj TSRMLS_CC); @@ -197,6 +258,17 @@ PHP_METHOD(ChannelCredentials, createComposite) { NULL); zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + wrapped_grpc_channel_credentials *cred1 = + Z_WRAPPED_GRPC_CHANNEL_CREDS_P(cred1_obj); + wrapped_grpc_call_credentials *cred2 = + Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); + grpc_channel_credentials *creds = + grpc_composite_channel_credentials_create(cred1->wrapped, + cred2->wrapped, NULL); + grpc_php_wrap_channel_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -218,7 +290,8 @@ static zend_function_entry channel_credentials_methods[] = { ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(ChannelCredentials, createInsecure, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_FE_END}; + PHP_FE_END +}; void grpc_init_channel_credentials(TSRMLS_D) { zend_class_entry ce; @@ -227,4 +300,13 @@ void grpc_init_channel_credentials(TSRMLS_D) { grpc_set_ssl_roots_override_callback(get_ssl_roots_override); ce.create_object = create_wrapped_grpc_channel_credentials; grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&channel_credentials_ce_handlers, + zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + channel_credentials_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_channel_credentials, std); + channel_credentials_ce_handlers.free_obj = + free_wrapped_grpc_channel_credentials; +#endif } diff --git a/src/php/ext/grpc/channel_credentials.h b/src/php/ext/grpc/channel_credentials.h index d89984ce60..44071b10f1 100755 --- a/src/php/ext/grpc/channel_credentials.h +++ b/src/php/ext/grpc/channel_credentials.h @@ -49,14 +49,37 @@ /* Class entry for the ChannelCredentials PHP class */ extern zend_class_entry *grpc_ce_channel_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_channel_credentials that can be associated * with a PHP object */ typedef struct wrapped_grpc_channel_credentials { zend_object std; + grpc_channel_credentials *wrapped; +} wrapped_grpc_channel_credentials; +#else + +/* Wrapper struct for grpc_channel_credentials that can be associated + * with a PHP object */ +typedef struct wrapped_grpc_channel_credentials { grpc_channel_credentials *wrapped; + zend_object std; } wrapped_grpc_channel_credentials; +static inline wrapped_grpc_channel_credentials +*wrapped_grpc_channel_creds_from_obj(zend_object *obj) { + return + (wrapped_grpc_channel_credentials *) + ((char*)(obj) - + XtOffsetOf(wrapped_grpc_channel_credentials, std)); +} + +#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \ + wrapped_grpc_channel_creds_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the ChannelCredentials PHP class */ void grpc_init_channel_credentials(TSRMLS_D); diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c index f4cb5b28cc..5edfa2da7d 100644 --- a/src/php/ext/grpc/php_grpc.c +++ b/src/php/ext/grpc/php_grpc.c @@ -64,15 +64,19 @@ const zend_function_entry grpc_functions[] = { */ zend_module_entry grpc_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 - STANDARD_MODULE_HEADER, + STANDARD_MODULE_HEADER, #endif - "grpc", grpc_functions, PHP_MINIT(grpc), - PHP_MSHUTDOWN(grpc), NULL, NULL, - PHP_MINFO(grpc), + "grpc", + grpc_functions, + PHP_MINIT(grpc), + PHP_MSHUTDOWN(grpc), + NULL, + NULL, + PHP_MINFO(grpc), #if ZEND_MODULE_API_NO >= 20010901 - PHP_GRPC_VERSION, + PHP_GRPC_VERSION, #endif - STANDARD_MODULE_PROPERTIES}; + STANDARD_MODULE_PROPERTIES}; /* }}} */ #ifdef COMPILE_DL_GRPC @@ -82,23 +86,24 @@ ZEND_GET_MODULE(grpc) /* {{{ PHP_INI */ /* Remove comments and fill if you need to have entries in php.ini -PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong, -global_value, zend_grpc_globals, grpc_globals) - STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL, -OnUpdateString, global_string, zend_grpc_globals, grpc_globals) -PHP_INI_END() + PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong, + global_value, zend_grpc_globals, grpc_globals) + STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL, + OnUpdateString, global_string, zend_grpc_globals, + grpc_globals) + PHP_INI_END() */ /* }}} */ /* {{{ php_grpc_init_globals */ /* Uncomment this function if you have INI entries -static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) -{ - grpc_globals->global_value = 0; - grpc_globals->global_string = NULL; -} + static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) + { + grpc_globals->global_value = 0; + grpc_globals->global_string = NULL; + } */ /* }}} */ @@ -106,7 +111,7 @@ static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) */ PHP_MINIT_FUNCTION(grpc) { /* If you have INI entries, uncomment these lines - REGISTER_INI_ENTRIES(); + REGISTER_INI_ENTRIES(); */ /* Register call error constants */ grpc_init(); @@ -246,8 +251,10 @@ PHP_MINIT_FUNCTION(grpc) { */ PHP_MSHUTDOWN_FUNCTION(grpc) { /* uncomment this line if you have INI entries - UNREGISTER_INI_ENTRIES(); + UNREGISTER_INI_ENTRIES(); */ + // WARNING: This function IS being called by PHP when the extension + // is unloaded but the logs were somehow suppressed. grpc_shutdown_timeval(TSRMLS_C); grpc_php_shutdown_completion_queue(TSRMLS_C); grpc_shutdown(); @@ -263,7 +270,7 @@ PHP_MINFO_FUNCTION(grpc) { php_info_print_table_end(); /* Remove comments if you have entries in php.ini - DISPLAY_INI_ENTRIES(); + DISPLAY_INI_ENTRIES(); */ } /* }}} */ @@ -272,12 +279,3 @@ PHP_MINFO_FUNCTION(grpc) { function definition, where the functions purpose is also documented. Please follow this convention for the convenience of others editing your code. */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h index 1d4834c50f..bd7ee75a6f 100644 --- a/src/php/ext/grpc/php_grpc.h +++ b/src/php/ext/grpc/php_grpc.h @@ -72,8 +72,8 @@ PHP_MSHUTDOWN_FUNCTION(grpc); PHP_MINFO_FUNCTION(grpc); /* - Declare any global variables you may need between the BEGIN - and END macros here: + Declare any global variables you may need between the BEGIN + and END macros here: ZEND_BEGIN_MODULE_GLOBALS(grpc) ZEND_END_MODULE_GLOBALS(grpc) diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c index 6df2e4f978..50fb2d0cf9 100644 --- a/src/php/ext/grpc/server.c +++ b/src/php/ext/grpc/server.c @@ -48,7 +48,6 @@ #include <stdbool.h> #include <grpc/grpc.h> -#include <grpc/support/log.h> #include <grpc/grpc_security.h> #include "completion_queue.h" @@ -59,6 +58,8 @@ zend_class_entry *grpc_ce_server; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_server */ void free_wrapped_grpc_server(void *object TSRMLS_DC) { wrapped_grpc_server *server = (wrapped_grpc_server *)object; @@ -69,6 +70,7 @@ void free_wrapped_grpc_server(void *object TSRMLS_DC) { gpr_inf_future(GPR_CLOCK_REALTIME), NULL); grpc_server_destroy(server->wrapped); } + zend_object_std_dtor(&server->std TSRMLS_CC); efree(server); } @@ -91,15 +93,51 @@ zend_object_value create_wrapped_grpc_server(zend_class_entry *class_type return retval; } +#else + +static zend_object_handlers server_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_server */ +static void free_wrapped_grpc_server(zend_object *object) { + wrapped_grpc_server *server = wrapped_grpc_server_from_obj(object); + if (server->wrapped != NULL) { + grpc_server_shutdown_and_notify(server->wrapped, completion_queue, NULL); + grpc_server_cancel_all_calls(server->wrapped); + grpc_completion_queue_pluck(completion_queue, NULL, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_server_destroy(server->wrapped); + } + zend_object_std_dtor(&server->std); +} + +/* Initializes an instance of wrapped_grpc_call to be associated with an object + * of a class specified by class_type */ +zend_object *create_wrapped_grpc_server(zend_class_entry *class_type) { + wrapped_grpc_server *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_server) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &server_ce_handlers; + return &intern->std; +} + +#endif + /** * Constructs a new instance of the Server class * @param array $args The arguments to pass to the server (optional) */ PHP_METHOD(Server, __construct) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_server *server = (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif zval *args_array = NULL; grpc_channel_args args; + /* "|a" == 1 optional array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &args_array) == FAILURE) { @@ -111,6 +149,8 @@ PHP_METHOD(Server, __construct) { if (args_array == NULL) { server->wrapped = grpc_server_create(NULL, NULL); } else { + //TODO(thinkerou): deal it if key of array is long, crash now on php7 + // and update unit test case php_grpc_read_args_array(args_array, &args TSRMLS_CC); server->wrapped = grpc_server_create(&args, NULL); efree(args.args); @@ -127,15 +167,22 @@ PHP_METHOD(Server, __construct) { */ PHP_METHOD(Server, requestCall) { grpc_call_error error_code; - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); grpc_call *call; grpc_call_details details; grpc_metadata_array metadata; - zval *result; grpc_event event; + +#if PHP_MAJOR_VERSION < 7 + wrapped_grpc_server *server = + (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); + zval *result; MAKE_STD_ZVAL(result); object_init(result); +#else + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); + object_init(return_value); +#endif + grpc_call_details_init(&details); grpc_metadata_array_init(&metadata); error_code = @@ -147,23 +194,48 @@ PHP_METHOD(Server, requestCall) { goto cleanup; } event = grpc_completion_queue_pluck(completion_queue, NULL, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); if (!event.success) { zend_throw_exception(spl_ce_LogicException, "Failed to request a call for some reason", 1 TSRMLS_CC); goto cleanup; } +#if PHP_MAJOR_VERSION < 7 add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC)); add_property_string(result, "method", details.method, true); add_property_string(result, "host", details.host, true); add_property_zval(result, "absolute_deadline", grpc_php_wrap_timeval(details.deadline TSRMLS_CC)); - add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata TSRMLS_CC)); + add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata + TSRMLS_CC)); + cleanup: grpc_call_details_destroy(&details); grpc_metadata_array_destroy(&metadata); RETURN_DESTROY_ZVAL(result); + +#else + + zval zv_call; + zval zv_timeval; + zval zv_md; + grpc_php_wrap_call(call, true, &zv_call); + grpc_php_wrap_timeval(details.deadline, &zv_timeval); + grpc_parse_metadata_array(&metadata, &zv_md); + + add_property_zval(return_value, "call", &zv_call); + add_property_string(return_value, "method", details.method); + add_property_string(return_value, "host", details.host); + add_property_zval(return_value, "absolute_deadline", &zv_timeval); + add_property_zval(return_value, "metadata", &zv_md); + + cleanup: + grpc_call_details_destroy(&details); + grpc_metadata_array_destroy(&metadata); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -172,13 +244,19 @@ cleanup: * @return true on success, false on failure */ PHP_METHOD(Server, addHttp2Port) { - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); const char *addr; +#if PHP_MAJOR_VERSION < 7 int addr_len; + wrapped_grpc_server *server = + (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + size_t addr_len; + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif + /* "s" == 1 string */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) + == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "add_http2_port expects a string", 1 TSRMLS_CC); return; @@ -187,11 +265,17 @@ PHP_METHOD(Server, addHttp2Port) { } PHP_METHOD(Server, addSecureHttp2Port) { - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); const char *addr; - int addr_len; zval *creds_obj; +#if PHP_MAJOR_VERSION < 7 + int addr_len; + wrapped_grpc_server *server = + (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + size_t addr_len; + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif + /* "sO" == 1 string, 1 object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len, &creds_obj, grpc_ce_server_credentials) == @@ -201,9 +285,14 @@ PHP_METHOD(Server, addSecureHttp2Port) { "add_http2_port expects a string and a ServerCredentials", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_server_credentials *creds = (wrapped_grpc_server_credentials *)zend_object_store_get_object( creds_obj TSRMLS_CC); +#else + wrapped_grpc_server_credentials *creds = + Z_WRAPPED_GRPC_SERVER_CREDS_P(creds_obj); +#endif RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr, creds->wrapped)); } @@ -213,21 +302,33 @@ PHP_METHOD(Server, addSecureHttp2Port) { * @return Void */ PHP_METHOD(Server, start) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_server *server = (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif grpc_server_start(server->wrapped); } static zend_function_entry server_methods[] = { - PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC) PHP_FE_END}; + PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; void grpc_init_server(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Server", server_methods); ce.create_object = create_wrapped_grpc_server; grpc_ce_server = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&server_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + server_ce_handlers.offset = XtOffsetOf(wrapped_grpc_server, std); + server_ce_handlers.free_obj = free_wrapped_grpc_server; +#endif } diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h index 022257f37c..a7df456a11 100755 --- a/src/php/ext/grpc/server.h +++ b/src/php/ext/grpc/server.h @@ -48,13 +48,33 @@ /* Class entry for the Server PHP class */ extern zend_class_entry *grpc_ce_server; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_server that can be associated with a PHP object */ typedef struct wrapped_grpc_server { zend_object std; + grpc_server *wrapped; +} wrapped_grpc_server; +#else + +/* Wrapper struct for grpc_server that can be associated with a PHP object */ +typedef struct wrapped_grpc_server { grpc_server *wrapped; + zend_object std; } wrapped_grpc_server; +static inline wrapped_grpc_server +*wrapped_grpc_server_from_obj(zend_object *obj) { + return (wrapped_grpc_server*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_server, std)); +} + +#define Z_WRAPPED_GRPC_SERVER_P(zv) \ + wrapped_grpc_server_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the Server class */ void grpc_init_server(TSRMLS_D); diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c index 505da10a28..296632d5bd 100644 --- a/src/php/ext/grpc/server_credentials.c +++ b/src/php/ext/grpc/server_credentials.c @@ -51,6 +51,8 @@ zend_class_entry *grpc_ce_server_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instace of wrapped_grpc_server_credentials */ void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) { wrapped_grpc_server_credentials *creds = @@ -58,6 +60,7 @@ void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) { if (creds->wrapped != NULL) { grpc_server_credentials_release(creds->wrapped); } + zend_object_std_dtor(&creds->std TSRMLS_CC); efree(creds); } @@ -81,7 +84,8 @@ zend_object_value create_wrapped_grpc_server_credentials( return retval; } -zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_DC) { +zval *grpc_php_wrap_server_credentials(grpc_server_credentials + *wrapped TSRMLS_DC) { zval *server_credentials_object; MAKE_STD_ZVAL(server_credentials_object); object_init_ex(server_credentials_object, grpc_ce_server_credentials); @@ -92,6 +96,43 @@ zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_D return server_credentials_object; } +#else + +static zend_object_handlers server_credentials_ce_handlers; + +/* Frees and destroys an instace of wrapped_grpc_server_credentials */ +static void free_wrapped_grpc_server_credentials(zend_object *object) { + wrapped_grpc_server_credentials *creds = + wrapped_grpc_server_creds_from_obj(object); + if (creds->wrapped != NULL) { + grpc_server_credentials_release(creds->wrapped); + } + zend_object_std_dtor(&creds->std); +} + +/* Initializes an instace of wrapped_grpc_server_credentials to be associated + * with an object of a class specified by class_type */ +zend_object *create_wrapped_grpc_server_credentials(zend_class_entry + *class_type) { + wrapped_grpc_server_credentials *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_server_credentials) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &server_credentials_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped, + zval *server_credentials_object) { + object_init_ex(server_credentials_object, grpc_ce_server_credentials); + wrapped_grpc_server_credentials *server_credentials = + Z_WRAPPED_GRPC_SERVER_CREDS_P(server_credentials_object); + server_credentials->wrapped = wrapped; +} + +#endif + /** * Create SSL credentials. * @param string pem_root_certs PEM encoding of the server root certificates @@ -103,7 +144,11 @@ PHP_METHOD(ServerCredentials, createSsl) { char *pem_root_certs = 0; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; +#if PHP_MAJOR_VERSION < 7 int root_certs_length = 0, private_key_length, cert_chain_length; +#else + size_t root_certs_length = 0, private_key_length, cert_chain_length; +#endif /* "s!ss" == 1 nullable string, 2 strings */ /* TODO: support multiple key cert pairs. */ @@ -120,17 +165,33 @@ PHP_METHOD(ServerCredentials, createSsl) { grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex( pem_root_certs, &pem_key_cert_pair, 1, GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_server_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } static zend_function_entry server_credentials_methods[] = { - PHP_ME(ServerCredentials, createSsl, NULL, - ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END}; + PHP_ME(ServerCredentials, createSsl, NULL, + ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_FE_END + }; void grpc_init_server_credentials(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\ServerCredentials", server_credentials_methods); ce.create_object = create_wrapped_grpc_server_credentials; grpc_ce_server_credentials = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&server_credentials_ce_handlers, + zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + server_credentials_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_server_credentials, std); + server_credentials_ce_handlers.free_obj = + free_wrapped_grpc_server_credentials; +#endif } diff --git a/src/php/ext/grpc/server_credentials.h b/src/php/ext/grpc/server_credentials.h index 7101d65000..d37fafc0dc 100755 --- a/src/php/ext/grpc/server_credentials.h +++ b/src/php/ext/grpc/server_credentials.h @@ -49,14 +49,34 @@ /* Class entry for the Server_Credentials PHP class */ extern zend_class_entry *grpc_ce_server_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_server_credentials that can be associated with a PHP * object */ typedef struct wrapped_grpc_server_credentials { zend_object std; + grpc_server_credentials *wrapped; +} wrapped_grpc_server_credentials; +#else + +typedef struct wrapped_grpc_server_credentials { grpc_server_credentials *wrapped; + zend_object std; } wrapped_grpc_server_credentials; +static inline wrapped_grpc_server_credentials +*wrapped_grpc_server_creds_from_obj(zend_object *obj) { + return (wrapped_grpc_server_credentials*) + ((char*)(obj) - + XtOffsetOf(wrapped_grpc_server_credentials, std)); +} + +#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \ + wrapped_grpc_server_creds_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the Server_Credentials PHP class */ void grpc_init_server_credentials(TSRMLS_D); diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c index 5e242162a8..8dc997c2dd 100644 --- a/src/php/ext/grpc/timeval.c +++ b/src/php/ext/grpc/timeval.c @@ -52,8 +52,14 @@ zend_class_entry *grpc_ce_timeval; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_call */ -void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { efree(object); } +void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { + wrapped_grpc_timeval *timeval = (wrapped_grpc_timeval *)object; + zend_object_std_dtor(&timeval->std TSRMLS_CC); + efree(timeval); +} /* Initializes an instance of wrapped_grpc_timeval to be associated with an * object of a class specified by class_type */ @@ -83,14 +89,50 @@ zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) { return timeval_object; } +#else + +static zend_object_handlers timeval_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_call */ +static void free_wrapped_grpc_timeval(zend_object *object) { + wrapped_grpc_timeval *timeval = wrapped_grpc_timeval_from_obj(object); + zend_object_std_dtor(&timeval->std); +} + +/* Initializes an instance of wrapped_grpc_timeval to be associated with an + * object of a class specified by class_type */ +zend_object *create_wrapped_grpc_timeval(zend_class_entry *class_type) { + wrapped_grpc_timeval *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_timeval) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &timeval_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_timeval(gpr_timespec wrapped, zval *timeval_object) { + object_init_ex(timeval_object, grpc_ce_timeval); + wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(timeval_object); + memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec)); +} + +#endif + /** * Constructs a new instance of the Timeval class * @param long $usec The number of microseconds in the interval */ PHP_METHOD(Timeval, __construct) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *timeval = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); long microseconds; +#else + wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + zend_long microseconds; +#endif + /* "l" == 1 long */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", µseconds) == FAILURE) { @@ -110,6 +152,7 @@ PHP_METHOD(Timeval, __construct) { */ PHP_METHOD(Timeval, add) { zval *other_obj; + /* "O" == 1 Object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj, grpc_ce_timeval) == FAILURE) { @@ -117,13 +160,23 @@ PHP_METHOD(Timeval, add) { "add expects a Timeval", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *self = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); wrapped_grpc_timeval *other = (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC); zval *sum = - grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) TSRMLS_CC); + grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(sum); +#else + wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); + + grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped), + return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -134,6 +187,7 @@ PHP_METHOD(Timeval, add) { */ PHP_METHOD(Timeval, subtract) { zval *other_obj; + /* "O" == 1 Object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj, grpc_ce_timeval) == FAILURE) { @@ -141,13 +195,22 @@ PHP_METHOD(Timeval, subtract) { "subtract expects a Timeval", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *self = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); wrapped_grpc_timeval *other = (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC); zval *diff = - grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) TSRMLS_CC); + grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(diff); +#else + wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); + grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped), + return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -158,7 +221,9 @@ PHP_METHOD(Timeval, subtract) { * @return long */ PHP_METHOD(Timeval, compare) { - zval *a_obj, *b_obj; + zval *a_obj; + zval *b_obj; + /* "OO" == 2 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &a_obj, grpc_ce_timeval, &b_obj, @@ -167,10 +232,15 @@ PHP_METHOD(Timeval, compare) { "compare expects two Timevals", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *a = (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC); wrapped_grpc_timeval *b = (wrapped_grpc_timeval *)zend_object_store_get_object(b_obj TSRMLS_CC); +#else + wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); + wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); +#endif long result = gpr_time_cmp(a->wrapped, b->wrapped); RETURN_LONG(result); } @@ -183,7 +253,10 @@ PHP_METHOD(Timeval, compare) { * @return bool True if $a and $b are within $threshold, False otherwise */ PHP_METHOD(Timeval, similar) { - zval *a_obj, *b_obj, *thresh_obj; + zval *a_obj; + zval *b_obj; + zval *thresh_obj; + /* "OOO" == 3 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &a_obj, grpc_ce_timeval, &b_obj, grpc_ce_timeval, @@ -192,6 +265,7 @@ PHP_METHOD(Timeval, similar) { "compare expects three Timevals", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *a = (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC); wrapped_grpc_timeval *b = @@ -199,6 +273,11 @@ PHP_METHOD(Timeval, similar) { wrapped_grpc_timeval *thresh = (wrapped_grpc_timeval *)zend_object_store_get_object( thresh_obj TSRMLS_CC); +#else + wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); + wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); + wrapped_grpc_timeval *thresh = Z_WRAPPED_GRPC_TIMEVAL_P(thresh_obj); +#endif int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped); RETURN_BOOL(result); } @@ -208,8 +287,13 @@ PHP_METHOD(Timeval, similar) { * @return Timeval The current time */ PHP_METHOD(Timeval, now) { +#if PHP_MAJOR_VERSION < 7 zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(now); +#else + grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME), return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -217,11 +301,18 @@ PHP_METHOD(Timeval, now) { * @return Timeval Zero length time interval */ PHP_METHOD(Timeval, zero) { +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_timeval_zero = grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_ZVAL(grpc_php_timeval_zero, false, /* Copy original before returning? */ true /* Destroy original before returning */); +#else + grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME), return_value); + RETURN_ZVAL(return_value, + false, /* Copy original before returning? */ + true /* Destroy original before returning */); +#endif } /** @@ -229,9 +320,14 @@ PHP_METHOD(Timeval, zero) { * @return Timeval Infinite future time value */ PHP_METHOD(Timeval, infFuture) { +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_timeval_inf_future = grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future); +#else + grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME), return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -239,9 +335,14 @@ PHP_METHOD(Timeval, infFuture) { * @return Timeval Infinite past time value */ PHP_METHOD(Timeval, infPast) { +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_timeval_inf_past = grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past); +#else + grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME), return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -249,28 +350,41 @@ PHP_METHOD(Timeval, infPast) { * @return void */ PHP_METHOD(Timeval, sleepUntil) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *this = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_timeval *this = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); +#endif gpr_sleep_until(this->wrapped); } static zend_function_entry timeval_methods[] = { - PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END}; + PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_FE_END +}; void grpc_init_timeval(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Timeval", timeval_methods); ce.create_object = create_wrapped_grpc_timeval; grpc_ce_timeval = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&timeval_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + timeval_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_timeval, std); + timeval_ce_handlers.free_obj = free_wrapped_grpc_timeval; +#endif } void grpc_shutdown_timeval(TSRMLS_D) {} diff --git a/src/php/ext/grpc/timeval.h b/src/php/ext/grpc/timeval.h index 7456eb6d58..d4eb2facde 100755 --- a/src/php/ext/grpc/timeval.h +++ b/src/php/ext/grpc/timeval.h @@ -50,12 +50,31 @@ extern zend_class_entry *grpc_ce_timeval; /* Wrapper struct for timeval that can be associated with a PHP object */ +#if PHP_MAJOR_VERSION < 7 + typedef struct wrapped_grpc_timeval { zend_object std; + gpr_timespec wrapped; +} wrapped_grpc_timeval; +#else + +typedef struct wrapped_grpc_timeval { gpr_timespec wrapped; + zend_object std; } wrapped_grpc_timeval; +static inline wrapped_grpc_timeval +*wrapped_grpc_timeval_from_obj(zend_object *obj) { + return (wrapped_grpc_timeval*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_timeval, std)); +} + +#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \ + wrapped_grpc_timeval_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initialize the Timeval PHP class */ void grpc_init_timeval(TSRMLS_D); @@ -63,6 +82,10 @@ void grpc_init_timeval(TSRMLS_D); void grpc_shutdown_timeval(TSRMLS_D); /* Creates a Timeval object that wraps the given timeval struct */ +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC); +#else +void grpc_php_wrap_timeval(gpr_timespec wrapped, zval *timeval_object); +#endif /* PHP_MAJOR_VERSION */ #endif /* NET_GRPC_PHP_GRPC_TIMEVAL_H_ */ diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php index df3fe85d44..2fec1bd9cc 100755..100644 --- a/src/php/lib/Grpc/BaseStub.php +++ b/src/php/lib/Grpc/BaseStub.php @@ -84,8 +84,8 @@ class BaseStub } if ($channel) { if (!is_a($channel, 'Channel')) { - throw new \Exception("The channel argument is not a". - "Channel object"); + throw new \Exception('The channel argument is not a'. + 'Channel object'); } $this->channel = $channel; } else { diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php index 95e51c5088..c2fdb94b86 100644 --- a/src/php/lib/Grpc/BidiStreamingCall.php +++ b/src/php/lib/Grpc/BidiStreamingCall.php @@ -113,6 +113,7 @@ class BidiStreamingCall extends AbstractCall ]); $this->trailing_metadata = $status_event->status->metadata; + return $status_event->status; } } diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php index 315a406735..4050f7ed06 100644 --- a/src/php/lib/Grpc/ClientStreamingCall.php +++ b/src/php/lib/Grpc/ClientStreamingCall.php @@ -88,6 +88,7 @@ class ClientStreamingCall extends AbstractCall $status = $event->status; $this->trailing_metadata = $status->metadata; + return [$this->deserializeResponse($event->message), $status]; } } diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php index 53599fe4ae..ba89d9f972 100644 --- a/src/php/lib/Grpc/ServerStreamingCall.php +++ b/src/php/lib/Grpc/ServerStreamingCall.php @@ -92,6 +92,7 @@ class ServerStreamingCall extends AbstractCall ]); $this->trailing_metadata = $status_event->status->metadata; + return $status_event->status; } } diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php index b114b771b8..a71b05dc93 100644 --- a/src/php/lib/Grpc/UnaryCall.php +++ b/src/php/lib/Grpc/UnaryCall.php @@ -77,6 +77,7 @@ class UnaryCall extends AbstractCall $status = $event->status; $this->trailing_metadata = $status->metadata; + return [$this->deserializeResponse($event->message), $status]; } } diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index 43b3199d92..bf40549a04 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -450,7 +450,7 @@ function statusCodeAndMessage($stub) { $echo_status = new grpc\testing\EchoStatus(); $echo_status->setCode(2); - $echo_status->setMessage("test status message"); + $echo_status->setMessage('test status message'); $request = new grpc\testing\SimpleRequest(); $request->setResponseStatus($echo_status); @@ -460,7 +460,7 @@ function statusCodeAndMessage($stub) hardAssert($status->code === 2, 'Received unexpected status code'); - hardAssert($status->details === "test status message", + hardAssert($status->details === 'test status message', 'Received unexpected status details'); $streaming_call = $stub->FullDuplexCall(); @@ -473,7 +473,7 @@ function statusCodeAndMessage($stub) $status = $streaming_call->getStatus(); hardAssert($status->code === 2, 'Received unexpected status code'); - hardAssert($status->details === "test status message", + hardAssert($status->details === 'test status message', 'Received unexpected status details'); } @@ -570,9 +570,9 @@ function _makeStub($args) } if ($test_case == 'unimplemented_method') { - $stub = new grpc\testing\UnimplementedServiceClient($server_address, $opts); + $stub = new grpc\testing\UnimplementedServiceClient($server_address, $opts); } else { - $stub = new grpc\testing\TestServiceClient($server_address, $opts); + $stub = new grpc\testing\TestServiceClient($server_address, $opts); } return $stub; diff --git a/src/php/tests/unit_tests/CallCredentialsTest.php b/src/php/tests/unit_tests/CallCredentialsTest.php index 5fec06cd13..1994c8afe5 100644 --- a/src/php/tests/unit_tests/CallCredentialsTest.php +++ b/src/php/tests/unit_tests/CallCredentialsTest.php @@ -148,7 +148,8 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase $this->call_credentials, $call_credentials2 ); - $this->assertSame('Grpc\CallCredentials', get_class($call_credentials3)); + $this->assertSame('Grpc\CallCredentials', + get_class($call_credentials3)); } /** diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php index fa026f0935..d736f51546 100755..100644 --- a/src/php/tests/unit_tests/CallTest.php +++ b/src/php/tests/unit_tests/CallTest.php @@ -50,6 +50,18 @@ class CallTest extends PHPUnit_Framework_TestCase Grpc\Timeval::infFuture()); } + public function tearDown() + { + unset($this->call); + unset($this->channel); + } + + public function testConstructor() + { + $this->assertSame('Grpc\Call', get_class($this->call)); + $this->assertObjectHasAttribute('channel', $this->call); + } + public function testAddEmptyMetadata() { $batch = [ @@ -81,7 +93,8 @@ class CallTest extends PHPUnit_Framework_TestCase { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'], - 'key2' => ['value2', 'value3'], ], + 'key2' => ['value2', + 'value3'], ], ]; $result = $this->call->startBatch($batch); $this->assertTrue($result->send_metadata); @@ -118,4 +131,38 @@ class CallTest extends PHPUnit_Framework_TestCase ]; $result = $this->call->startBatch($batch); } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstuctor() + { + $this->call = new Grpc\Call(); + $this->assertNull($this->call); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstuctor2() + { + $this->call = new Grpc\Call('hi', 'hi', 'hi'); + $this->assertNull($this->call); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidSetCredentials() + { + $this->call->setCredentials('hi'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidSetCredentials2() + { + $this->call->setCredentials([]); + } } diff --git a/src/php/tests/unit_tests/ChannelCredentialsTest.php b/src/php/tests/unit_tests/ChannelCredentialsTest.php index 56c1d8f006..e822929ccd 100644 --- a/src/php/tests/unit_tests/ChannelCredentialsTest.php +++ b/src/php/tests/unit_tests/ChannelCredentialsTest.php @@ -42,10 +42,23 @@ class ChanellCredentialsTest extends PHPUnit_Framework_TestCase { } - public function testCreateDefault() + public function testCreateSslWith3Null() { - $channel_credentials = Grpc\ChannelCredentials::createDefault(); - $this->assertSame('Grpc\ChannelCredentials', get_class($channel_credentials)); + $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null, + null); + $this->assertNotNull($channel_credentials); + } + + public function testCreateSslWith3NullString() + { + $channel_credentials = Grpc\ChannelCredentials::createSsl('', '', ''); + $this->assertNotNull($channel_credentials); + } + + public function testCreateInsecure() + { + $channel_credentials = Grpc\ChannelCredentials::createInsecure(); + $this->assertNull($channel_credentials); } /** @@ -64,10 +77,4 @@ class ChanellCredentialsTest extends PHPUnit_Framework_TestCase $channel_credentials = Grpc\ChannelCredentials::createComposite( 'something', 'something'); } - - public function testCreateInsecure() - { - $channel_credentials = Grpc\ChannelCredentials::createInsecure(); - $this->assertNull($channel_credentials); - } } diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php index a1f9053c39..4b35b1a28c 100644 --- a/src/php/tests/unit_tests/ChannelTest.php +++ b/src/php/tests/unit_tests/ChannelTest.php @@ -40,6 +40,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase public function tearDown() { + unset($this->channel); } public function testInsecureCredentials() @@ -53,6 +54,82 @@ class ChannelTest extends PHPUnit_Framework_TestCase $this->assertSame('Grpc\Channel', get_class($this->channel)); } + public function testGetConnectivityState() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState(); + $this->assertEquals(0, $state); + } + + public function testGetConnectivityStateWithInt() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState(123); + $this->assertEquals(0, $state); + } + + public function testGetConnectivityStateWithString() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState('hello'); + $this->assertEquals(0, $state); + } + + public function testGetConnectivityStateWithBool() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState(true); + $this->assertEquals(0, $state); + } + + public function testGetTarget() + { + $this->channel = new Grpc\Channel('localhost:8888', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $target = $this->channel->getTarget(); + $this->assertTrue(is_string($target)); + } + + public function testWatchConnectivityState() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $time = new Grpc\Timeval(1000); + $state = $this->channel->watchConnectivityState(123, $time); + $this->assertTrue($state); + unset($time); + } + + public function testClose() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->assertNotNull($this->channel); + $this->channel->close(); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstructorWithNull() + { + $this->channel = new Grpc\Channel(); + $this->assertNull($this->channel); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstructorWith() + { + $this->channel = new Grpc\Channel('localhost', 'invalid'); + $this->assertNull($this->channel); + } + /** * @expectedException InvalidArgumentException */ @@ -78,4 +155,34 @@ class ChannelTest extends PHPUnit_Framework_TestCase ] ); } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidGetConnectivityStateWithArray() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->channel->getConnectivityState([]); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidWatchConnectivityState() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->channel->watchConnectivityState([]); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidWatchConnectivityState2() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->channel->watchConnectivityState(1, 'hi'); + } } diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php index 2b09f9d112..09364580c0 100755..100644 --- a/src/php/tests/unit_tests/EndToEndTest.php +++ b/src/php/tests/unit_tests/EndToEndTest.php @@ -521,7 +521,8 @@ class EndToEndTest extends PHPUnit_Framework_TestCase public function testGetConnectivityState() { - $this->assertTrue($this->channel->getConnectivityState() == Grpc\CHANNEL_IDLE); + $this->assertTrue($this->channel->getConnectivityState() == + Grpc\CHANNEL_IDLE); } public function testWatchConnectivityStateFailed() diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php index c388ee5031..c388ee5031 100755..100644 --- a/src/php/tests/unit_tests/SecureEndToEndTest.php +++ b/src/php/tests/unit_tests/SecureEndToEndTest.php diff --git a/src/php/tests/unit_tests/ServerTest.php b/src/php/tests/unit_tests/ServerTest.php index 76aaa06970..f2346ab113 100644 --- a/src/php/tests/unit_tests/ServerTest.php +++ b/src/php/tests/unit_tests/ServerTest.php @@ -36,10 +36,70 @@ class ServerTest extends PHPUnit_Framework_TestCase { public function setUp() { + $this->server = null; } public function tearDown() { + unset($this->server); + } + + public function testConstructorWithNull() + { + $this->server = new Grpc\Server(); + $this->assertNotNull($this->server); + } + + public function testConstructorWithNullArray() + { + $this->server = new Grpc\Server([]); + $this->assertNotNull($this->server); + } + + public function testConstructorWithArray() + { + // key of array must be string + $this->server = new Grpc\Server(['ip' => '127.0.0.1', + 'port' => '8080', ]); + $this->assertNotNull($this->server); + } + + public function testRequestCall() + { + $this->server = new Grpc\Server(); + $port = $this->server->addHttp2Port('0.0.0.0:8888'); + $this->server->start(); + $channel = new Grpc\Channel('localhost:8888', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + + $deadline = Grpc\Timeval::infFuture(); + $call = new Grpc\Call($channel, 'dummy_method', $deadline); + + $event = $call->startBatch([Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + ]); + + $c = $this->server->requestCall(); + $this->assertObjectHasAttribute('call', $c); + $this->assertObjectHasAttribute('method', $c); + $this->assertSame('dummy_method', $c->method); + $this->assertObjectHasAttribute('host', $c); + $this->assertTrue(is_string($c->host)); + $this->assertObjectHasAttribute('absolute_deadline', $c); + $this->assertObjectHasAttribute('metadata', $c); + + unset($call); + unset($channel); + } + + private function createSslObj() + { + $server_credentials = Grpc\ServerCredentials::createSsl( + null, + file_get_contents(dirname(__FILE__).'/../data/server1.key'), + file_get_contents(dirname(__FILE__).'/../data/server1.pem')); + + return $server_credentials; } /** @@ -47,7 +107,8 @@ class ServerTest extends PHPUnit_Framework_TestCase */ public function testInvalidConstructor() { - $server = new Grpc\Server('invalid_host'); + $this->server = new Grpc\Server('invalid_host'); + $this->assertNull($this->server); } /** @@ -56,7 +117,7 @@ class ServerTest extends PHPUnit_Framework_TestCase public function testInvalidAddHttp2Port() { $this->server = new Grpc\Server([]); - $this->port = $this->server->addHttp2Port(['0.0.0.0:0']); + $port = $this->server->addHttp2Port(['0.0.0.0:0']); } /** @@ -65,6 +126,24 @@ class ServerTest extends PHPUnit_Framework_TestCase public function testInvalidAddSecureHttp2Port() { $this->server = new Grpc\Server([]); - $this->port = $this->server->addSecureHttp2Port(['0.0.0.0:0']); + $port = $this->server->addSecureHttp2Port(['0.0.0.0:0']); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidAddSecureHttp2Port2() + { + $this->server = new Grpc\Server(); + $port = $this->server->addSecureHttp2Port('0.0.0.0:0'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidAddSecureHttp2Port3() + { + $this->server = new Grpc\Server(); + $port = $this->server->addSecureHttp2Port('0.0.0.0:0', 'invalid'); } } diff --git a/src/php/tests/unit_tests/TimevalTest.php b/src/php/tests/unit_tests/TimevalTest.php index a3dbce079f..2d19f64c79 100755..100644 --- a/src/php/tests/unit_tests/TimevalTest.php +++ b/src/php/tests/unit_tests/TimevalTest.php @@ -33,6 +33,57 @@ */ class TimevalTest extends PHPUnit_Framework_TestCase { + public function setUp() + { + } + + public function tearDown() + { + unset($this->time); + } + + public function testConstructorWithInt() + { + $this->time = new Grpc\Timeval(1234); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithNegative() + { + $this->time = new Grpc\Timeval(-123); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithZero() + { + $this->time = new Grpc\Timeval(0); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithOct() + { + $this->time = new Grpc\Timeval(0123); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithHex() + { + $this->time = new Grpc\Timeval(0x1A); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithFloat() + { + $this->time = new Grpc\Timeval(123.456); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + public function testCompareSame() { $zero = Grpc\Timeval::zero(); @@ -70,6 +121,7 @@ class TimevalTest extends PHPUnit_Framework_TestCase public function testNowAndAdd() { $now = Grpc\Timeval::now(); + $this->assertNotNull($now); $delta = new Grpc\Timeval(1000); $deadline = $now->add($delta); $this->assertGreaterThan(0, Grpc\Timeval::compare($deadline, $now)); @@ -154,5 +206,6 @@ class TimevalTest extends PHPUnit_Framework_TestCase public function testSimilarInvalidParam() { $a = Grpc\Timeval::similar(1000, 1100, 1200); + $this->assertNull($delta); } } diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto index 20496a8116..ece6910815 100644 --- a/src/proto/grpc/testing/control.proto +++ b/src/proto/grpc/testing/control.proto @@ -229,4 +229,7 @@ message ScenarioResult { repeated int32 server_cores = 5; // An after-the-fact computed summary ScenarioResultSummary summary = 6; + // Information on success or failure of each worker + repeated bool client_success = 7; + repeated bool server_success = 8; } diff --git a/src/python/grpcio/_unixccompiler_patch.py b/src/python/grpcio/_unixccompiler_patch.py new file mode 100644 index 0000000000..894c3ef395 --- /dev/null +++ b/src/python/grpcio/_unixccompiler_patch.py @@ -0,0 +1,77 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Covers inadequacies in distutils.""" + +from distutils import ccompiler +from distutils import errors +from distutils import unixccompiler +import os +import os.path +import shlex +import shutil +import sys +import tempfile + +def _unix_commandfile_spawn(self, command): + """Wrapper around distutils.util.spawn that attempts to use command files. + + Meant to replace the CCompiler method `spawn` on UnixCCompiler and its + derivatives (e.g. the MinGW32 compiler). + + Some commands like `gcc` (and friends like `clang`) support command files to + work around shell command length limits. + """ + # Sometimes distutils embeds the executables as full strings including some + # hard-coded flags rather than as lists. + command = list(shlex.split(command[0])) + list(command[1:]) + command_base = os.path.basename(command[0].strip()) + if command_base == 'ccache': + command_base = command[:2] + command_args = command[2:] + elif command_base.startswith('ccache') or command_base in ['gcc', 'clang', 'clang++', 'g++']: + command_base = command[:1] + command_args = command[1:] + else: + return ccompiler.CCompiler.spawn(self, command) + temporary_directory = tempfile.mkdtemp() + command_filename = os.path.abspath(os.path.join(temporary_directory, 'command')) + with open(command_filename, 'w') as command_file: + escaped_args = [arg.replace('\\', '\\\\') for arg in command_args] + command_file.write(' '.join(escaped_args)) + modified_command = command_base + ['@{}'.format(command_filename)] + result = ccompiler.CCompiler.spawn(self, modified_command) + shutil.rmtree(temporary_directory) + return result + + +def monkeypatch_unix_compiler(): + """Monkeypatching is dumb, but it's either that or we become maintainers of + something much, much bigger.""" + unixccompiler.UnixCCompiler.spawn = _unix_commandfile_spawn diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index 3f91954d5f..86a73fa836 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -58,10 +58,31 @@ CONF_PY_ADDENDUM = """ extensions.append('sphinx.ext.napoleon') napoleon_google_docstring = True napoleon_numpy_docstring = True +napoleon_include_special_with_doc = True html_theme = 'sphinx_rtd_theme' """ +API_GLOSSARY = """ + +Glossary +================ + +.. glossary:: + + metadatum + A key-value pair included in the HTTP header. It is a + 2-tuple where the first entry is the key and the + second is the value, i.e. (key, value). The metadata key is an ASCII str, + and must be a valid HTTP header name. The metadata value can be + either a valid HTTP ASCII str, or bytes. If bytes are provided, + the key must end with '-bin', i.e. + ``('binary-metadata-bin', b'\\x00\\xFF')`` + + metadata + A sequence of metadatum. +""" + class CommandError(Exception): """Simple exception class for GRPC custom commands.""" @@ -131,6 +152,9 @@ class SphinxDocumentation(setuptools.Command): conf_filepath = os.path.join('doc', 'src', 'conf.py') with open(conf_filepath, 'a') as conf_file: conf_file.write(CONF_PY_ADDENDUM) + glossary_filepath = os.path.join('doc', 'src', 'grpc.rst') + with open(glossary_filepath, 'a') as glossary_filepath: + glossary_filepath.write(API_GLOSSARY) sphinx.main(['', os.path.join('doc', 'src'), os.path.join('doc', 'build')]) diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index b3eeaad1f7..513839df7d 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -312,7 +312,7 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): This method blocks until the value is available. Returns: - The initial metadata as a sequence of pairs of bytes. + The initial :term:`metadata`. """ raise NotImplementedError() @@ -323,7 +323,7 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): This method blocks until the value is available. Returns: - The trailing metadata as a sequence of pairs of bytes. + The trailing :term:`metadata`. """ raise NotImplementedError() @@ -345,7 +345,7 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): This method blocks until the value is available. Returns: - The bytes of the details of the RPC. + The details string of the RPC. """ raise NotImplementedError() @@ -394,8 +394,7 @@ class AuthMetadataPluginCallback(six.with_metaclass(abc.ABCMeta)): """Inform the gRPC runtime of the metadata to construct a CallCredentials. Args: - metadata: An iterable of 2-sequences (e.g. tuples) of metadata key/value - pairs. + metadata: The :term:`metadata` used to construct the CallCredentials. error: An Exception to indicate error or None to indicate success. """ raise NotImplementedError() @@ -442,7 +441,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request: The request value for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -463,7 +462,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request: The request value for the RPC. timeout: An optional durating of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -484,7 +483,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request: The request value for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -507,7 +506,7 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request: The request value for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: An optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -530,7 +529,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -553,7 +552,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -575,7 +574,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -599,7 +598,7 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. - metadata: An optional sequence of pairs of bytes to be transmitted to the + metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. @@ -707,7 +706,7 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """Accesses the metadata from the invocation-side of the RPC. Returns: - The invocation metadata object as a sequence of pairs of bytes. + The invocation :term:`metadata`. """ raise NotImplementedError() @@ -728,8 +727,7 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): service-side initial metadata to transmit. Args: - initial_metadata: The initial metadata of the RPC as a sequence of pairs - of bytes. + initial_metadata: The initial :term:`metadata`. """ raise NotImplementedError() @@ -741,8 +739,7 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): service-side trailing metadata to transmit. Args: - trailing_metadata: The trailing metadata of the RPC as a sequence of pairs - of bytes. + trailing_metadata: The trailing :term:`metadata`. """ raise NotImplementedError() @@ -767,7 +764,7 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): details to transmit. Args: - details: The details bytes of the RPC to be transmitted to + details: The details string of the RPC to be transmitted to the invocation side of the RPC. """ raise NotImplementedError() @@ -815,7 +812,7 @@ class HandlerCallDetails(six.with_metaclass(abc.ABCMeta)): """Describes an RPC that has just arrived for service. Attributes: method: The method name of the RPC. - invocation_metadata: The metadata from the invocation side of the RPC. + invocation_metadata: The :term:`metadata` from the invocation side of the RPC. """ @@ -1091,37 +1088,41 @@ def access_token_call_credentials(access_token): _auth.AccessTokenCallCredentials(access_token)) -def composite_call_credentials(call_credentials, additional_call_credentials): - """Compose two CallCredentials to make a new one. +def composite_call_credentials(*call_credentials): + """Compose multiple CallCredentials to make a new CallCredentials. Args: - call_credentials: A CallCredentials object. - additional_call_credentials: Another CallCredentials object to compose on - top of call_credentials. + *call_credentials: At least two CallCredentials objects. Returns: - A new CallCredentials composed of the two given CallCredentials. + A CallCredentials object composed of the given CallCredentials objects. """ + from grpc import _credential_composition + cygrpc_call_credentials = tuple( + single_call_credentials._credentials + for single_call_credentials in call_credentials) return CallCredentials( - _cygrpc.call_credentials_composite( - call_credentials._credentials, - additional_call_credentials._credentials)) + _credential_composition.call(cygrpc_call_credentials)) -def composite_channel_credentials(channel_credentials, call_credentials): - """Compose a ChannelCredentials and a CallCredentials. +def composite_channel_credentials(channel_credentials, *call_credentials): + """Compose a ChannelCredentials and one or more CallCredentials objects. Args: channel_credentials: A ChannelCredentials. - call_credentials: A CallCredentials. + *call_credentials: One or more CallCredentials objects. Returns: A ChannelCredentials composed of the given ChannelCredentials and - CallCredentials. + CallCredentials objects. """ + from grpc import _credential_composition + cygrpc_call_credentials = tuple( + single_call_credentials._credentials + for single_call_credentials in call_credentials) return ChannelCredentials( - _cygrpc.channel_credentials_composite( - channel_credentials._credentials, call_credentials._credentials)) + _credential_composition.channel( + channel_credentials._credentials, cygrpc_call_credentials)) def ssl_server_credentials( @@ -1207,25 +1208,23 @@ def secure_channel(target, credentials, options=None): return _channel.Channel(target, options, credentials._credentials) -def server(generic_rpc_handlers, thread_pool, options=None): +def server(thread_pool, handlers=None): """Creates a Server with which RPCs can be serviced. - The GenericRpcHandlers passed to this function needn't be the only - GenericRpcHandlers that will be used to serve RPCs; others may be added later - by calling add_generic_rpc_handlers any time before the returned server is - started. - Args: - generic_rpc_handlers: Some number of GenericRpcHandlers that will be used - to service RPCs after the returned Server is started. thread_pool: A futures.ThreadPoolExecutor to be used by the returned Server to service RPCs. + handlers: An optional sequence of GenericRpcHandlers to be used to service + RPCs after the returned Server is started. These handlers need not be the + only handlers the server will use to service RPCs; other handlers may + later be added by calling add_generic_rpc_handlers any time before the + returned Server is started. Returns: A Server with which RPCs can be serviced. """ from grpc import _server - return _server.Server(generic_rpc_handlers, thread_pool) + return _server.Server(thread_pool, () if handlers is None else handlers) ################################### __all__ ################################# diff --git a/src/python/grpcio/grpc/_adapter/.gitignore b/src/python/grpcio/grpc/_adapter/.gitignore deleted file mode 100644 index a6f96cd6db..0000000000 --- a/src/python/grpcio/grpc/_adapter/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.a -*.so -*.dll -*.pyc -*.pyd diff --git a/src/python/grpcio/grpc/_adapter/_common.py b/src/python/grpcio/grpc/_adapter/_common.py deleted file mode 100644 index 492849f4cb..0000000000 --- a/src/python/grpcio/grpc/_adapter/_common.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State used by both invocation-side and service-side code.""" - -import enum - - -@enum.unique -class HighWrite(enum.Enum): - """The possible categories of high-level write state.""" - - OPEN = 'OPEN' - CLOSED = 'CLOSED' - - -class WriteState(object): - """A description of the state of writing to an RPC. - - Attributes: - low: A side-specific value describing the low-level state of writing. - high: A HighWrite value describing the high-level state of writing. - pending: A list of bytestrings for the RPC waiting to be written to the - other side of the RPC. - """ - - def __init__(self, low, high, pending): - self.low = low - self.high = high - self.pending = pending - - -class CommonRPCState(object): - """A description of an RPC's state. - - Attributes: - write: A WriteState describing the state of writing to the RPC. - sequence_number: The lowest-unused sequence number for use in generating - tickets locally describing the progress of the RPC. - deserializer: The behavior to be used to deserialize payload bytestreams - taken off the wire. - serializer: The behavior to be used to serialize payloads to be sent on the - wire. - """ - - def __init__(self, write, sequence_number, deserializer, serializer): - self.write = write - self.sequence_number = sequence_number - self.deserializer = deserializer - self.serializer = serializer diff --git a/src/python/grpcio/grpc/_adapter/_intermediary_low.py b/src/python/grpcio/grpc/_adapter/_intermediary_low.py deleted file mode 100644 index 9698ffeabf..0000000000 --- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py +++ /dev/null @@ -1,258 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Temporary old _low-like layer. - -Eases refactoring burden while we overhaul the Python framework. - -Plan: - The layers used to look like: - ... # outside _adapter - fore.py + rear.py # visible outside _adapter - _low - _c - The layers currently look like: - ... # outside _adapter - fore.py + rear.py # visible outside _adapter - _low_intermediary # adapter for new '_low' to old '_low' - _low # new '_low' - _c # new '_c' - We will later remove _low_intermediary after refactoring of fore.py and - rear.py according to the ticket system refactoring and get: - ... # outside _adapter, refactored - fore.py + rear.py # visible outside _adapter, refactored - _low # new '_low' - _c # new '_c' -""" - -import collections -import enum - -from grpc._adapter import _low -from grpc._adapter import _types - -_IGNORE_ME_TAG = object() -Code = _types.StatusCode -WriteFlags = _types.OpWriteFlags - - -class Status(collections.namedtuple('Status', ['code', 'details'])): - """Describes an RPC's overall status.""" - - -class ServiceAcceptance( - collections.namedtuple( - 'ServiceAcceptance', ['call', 'method', 'host', 'deadline'])): - """Describes an RPC on the service side at the start of service.""" - - -class Event( - collections.namedtuple( - 'Event', - ['kind', 'tag', 'write_accepted', 'complete_accepted', - 'service_acceptance', 'bytes', 'status', 'metadata'])): - """Describes an event emitted from a completion queue.""" - - @enum.unique - class Kind(enum.Enum): - """Describes the kind of an event.""" - - STOP = object() - WRITE_ACCEPTED = object() - COMPLETE_ACCEPTED = object() - SERVICE_ACCEPTED = object() - READ_ACCEPTED = object() - METADATA_ACCEPTED = object() - FINISH = object() - - -class _TagAdapter(collections.namedtuple('_TagAdapter', [ - 'user_tag', - 'kind' - ])): - pass - - -class Call(object): - """Adapter from old _low.Call interface to new _low.Call.""" - - def __init__(self, channel, completion_queue, method, host, deadline): - self._internal = channel._internal.create_call( - completion_queue._internal, method, host, deadline) - self._metadata = [] - - @staticmethod - def _from_internal(internal): - call = Call.__new__(Call) - call._internal = internal - call._metadata = [] - return call - - def invoke(self, completion_queue, metadata_tag, finish_tag): - err = self._internal.start_batch([ - _types.OpArgs.send_initial_metadata(self._metadata) - ], _IGNORE_ME_TAG) - if err != _types.CallError.OK: - return err - err = self._internal.start_batch([ - _types.OpArgs.recv_initial_metadata() - ], _TagAdapter(metadata_tag, Event.Kind.METADATA_ACCEPTED)) - if err != _types.CallError.OK: - return err - err = self._internal.start_batch([ - _types.OpArgs.recv_status_on_client() - ], _TagAdapter(finish_tag, Event.Kind.FINISH)) - return err - - def write(self, message, tag, flags): - return self._internal.start_batch([ - _types.OpArgs.send_message(message, flags) - ], _TagAdapter(tag, Event.Kind.WRITE_ACCEPTED)) - - def complete(self, tag): - return self._internal.start_batch([ - _types.OpArgs.send_close_from_client() - ], _TagAdapter(tag, Event.Kind.COMPLETE_ACCEPTED)) - - def accept(self, completion_queue, tag): - return self._internal.start_batch([ - _types.OpArgs.recv_close_on_server() - ], _TagAdapter(tag, Event.Kind.FINISH)) - - def add_metadata(self, key, value): - self._metadata.append((key, value)) - - def premetadata(self): - result = self._internal.start_batch([ - _types.OpArgs.send_initial_metadata(self._metadata) - ], _IGNORE_ME_TAG) - self._metadata = [] - return result - - def read(self, tag): - return self._internal.start_batch([ - _types.OpArgs.recv_message() - ], _TagAdapter(tag, Event.Kind.READ_ACCEPTED)) - - def status(self, status, tag): - return self._internal.start_batch([ - _types.OpArgs.send_status_from_server( - self._metadata, status.code, status.details) - ], _TagAdapter(tag, Event.Kind.COMPLETE_ACCEPTED)) - - def cancel(self): - return self._internal.cancel() - - def peer(self): - return self._internal.peer() - - def set_credentials(self, creds): - return self._internal.set_credentials(creds) - - -class Channel(object): - """Adapter from old _low.Channel interface to new _low.Channel.""" - - def __init__(self, hostport, channel_credentials, server_host_override=None): - args = [] - if server_host_override: - args.append((_types.GrpcChannelArgumentKeys.SSL_TARGET_NAME_OVERRIDE.value, server_host_override)) - self._internal = _low.Channel(hostport, args, channel_credentials) - - -class CompletionQueue(object): - """Adapter from old _low.CompletionQueue interface to new _low.CompletionQueue.""" - - def __init__(self): - self._internal = _low.CompletionQueue() - - def get(self, deadline=None): - if deadline is None: - ev = self._internal.next(float('+inf')) - else: - ev = self._internal.next(deadline) - if ev is None: - return None - elif ev.tag is _IGNORE_ME_TAG: - return self.get(deadline) - elif ev.type == _types.EventType.QUEUE_SHUTDOWN: - kind = Event.Kind.STOP - tag = None - write_accepted = None - complete_accepted = None - service_acceptance = None - message_bytes = None - status = None - metadata = None - elif ev.type == _types.EventType.OP_COMPLETE: - kind = ev.tag.kind - tag = ev.tag.user_tag - write_accepted = ev.success if kind == Event.Kind.WRITE_ACCEPTED else None - complete_accepted = ev.success if kind == Event.Kind.COMPLETE_ACCEPTED else None - service_acceptance = ServiceAcceptance(Call._from_internal(ev.call), ev.call_details.method, ev.call_details.host, ev.call_details.deadline) if kind == Event.Kind.SERVICE_ACCEPTED else None - message_bytes = ev.results[0].message if kind == Event.Kind.READ_ACCEPTED else None - status = Status(ev.results[0].status.code, ev.results[0].status.details) if (kind == Event.Kind.FINISH and ev.results[0].status) else Status(_types.StatusCode.CANCELLED if ev.results[0].cancelled else _types.StatusCode.OK, '') if len(ev.results) > 0 and ev.results[0].cancelled is not None else None - metadata = ev.results[0].initial_metadata if (kind in [Event.Kind.SERVICE_ACCEPTED, Event.Kind.METADATA_ACCEPTED]) else (ev.results[0].trailing_metadata if kind == Event.Kind.FINISH else None) - else: - raise RuntimeError('unknown event') - result_ev = Event(kind=kind, tag=tag, write_accepted=write_accepted, complete_accepted=complete_accepted, service_acceptance=service_acceptance, bytes=message_bytes, status=status, metadata=metadata) - return result_ev - - def stop(self): - self._internal.shutdown() - - -class Server(object): - """Adapter from old _low.Server interface to new _low.Server.""" - - def __init__(self, completion_queue): - self._internal = _low.Server(completion_queue._internal, []) - self._internal_cq = completion_queue._internal - - def add_http2_addr(self, addr): - return self._internal.add_http2_port(addr) - - def add_secure_http2_addr(self, addr, server_credentials): - if server_credentials is None: - return self._internal.add_http2_port(addr, None) - else: - return self._internal.add_http2_port(addr, server_credentials) - - def start(self): - return self._internal.start() - - def service(self, tag): - return self._internal.request_call(self._internal_cq, _TagAdapter(tag, Event.Kind.SERVICE_ACCEPTED)) - - def cancel_all_calls(self): - self._internal.cancel_all_calls() - - def stop(self): - return self._internal.shutdown(_TagAdapter(None, Event.Kind.STOP)) - diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py deleted file mode 100644 index 48410167a0..0000000000 --- a/src/python/grpcio/grpc/_adapter/_low.py +++ /dev/null @@ -1,229 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import threading - -from grpc import _grpcio_metadata -from grpc import _plugin_wrapping -from grpc._cython import cygrpc -from grpc._adapter import _types - -_USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__) - -ChannelCredentials = cygrpc.ChannelCredentials -CallCredentials = cygrpc.CallCredentials -ServerCredentials = cygrpc.ServerCredentials - -channel_credentials_composite = cygrpc.channel_credentials_composite -call_credentials_composite = cygrpc.call_credentials_composite - -def server_credentials_ssl(root_credentials, pair_sequence, force_client_auth): - return cygrpc.server_credentials_ssl( - root_credentials, - [cygrpc.SslPemKeyCertPair(key, pem) for key, pem in pair_sequence], - force_client_auth) - -def channel_credentials_ssl( - root_certificates, private_key, certificate_chain): - pair = None - if private_key is not None or certificate_chain is not None: - pair = cygrpc.SslPemKeyCertPair(private_key, certificate_chain) - return cygrpc.channel_credentials_ssl(root_certificates, pair) - - -call_credentials_metadata_plugin = ( - _plugin_wrapping.call_credentials_metadata_plugin) - - -class CompletionQueue(_types.CompletionQueue): - - def __init__(self): - self.completion_queue = cygrpc.CompletionQueue() - - def next(self, deadline=float('+inf')): - raw_event = self.completion_queue.poll(cygrpc.Timespec(deadline)) - if raw_event.type == cygrpc.CompletionType.queue_timeout: - return None - event_type = raw_event.type - event_tag = raw_event.tag - event_call = Call(raw_event.operation_call) - if raw_event.request_call_details: - event_call_details = _types.CallDetails( - raw_event.request_call_details.method, - raw_event.request_call_details.host, - float(raw_event.request_call_details.deadline)) - else: - event_call_details = None - event_success = raw_event.success - event_results = [] - if raw_event.is_new_request: - event_results.append(_types.OpResult( - _types.OpType.RECV_INITIAL_METADATA, raw_event.request_metadata, - None, None, None, None)) - else: - if raw_event.batch_operations: - for operation in raw_event.batch_operations: - result_type = operation.type - result_initial_metadata = operation.received_metadata_or_none - result_trailing_metadata = operation.received_metadata_or_none - result_message = operation.received_message_or_none - if result_message is not None: - result_message = result_message.bytes() - result_cancelled = operation.received_cancelled_or_none - if operation.has_status: - result_status = _types.Status( - operation.received_status_code_or_none, - operation.received_status_details_or_none) - else: - result_status = None - event_results.append( - _types.OpResult(result_type, result_initial_metadata, - result_trailing_metadata, result_message, - result_status, result_cancelled)) - return _types.Event(event_type, event_tag, event_call, event_call_details, - event_results, event_success) - - def shutdown(self): - self.completion_queue.shutdown() - - -class Call(_types.Call): - - def __init__(self, call): - self.call = call - - def start_batch(self, ops, tag): - translated_ops = [] - for op in ops: - if op.type == _types.OpType.SEND_INITIAL_METADATA: - translated_op = cygrpc.operation_send_initial_metadata( - cygrpc.Metadata( - cygrpc.Metadatum(key, value) - for key, value in op.initial_metadata), - op.flags) - elif op.type == _types.OpType.SEND_MESSAGE: - translated_op = cygrpc.operation_send_message(op.message, op.flags) - elif op.type == _types.OpType.SEND_CLOSE_FROM_CLIENT: - translated_op = cygrpc.operation_send_close_from_client(op.flags) - elif op.type == _types.OpType.SEND_STATUS_FROM_SERVER: - translated_op = cygrpc.operation_send_status_from_server( - cygrpc.Metadata( - cygrpc.Metadatum(key, value) - for key, value in op.trailing_metadata), - op.status.code, - op.status.details, - op.flags) - elif op.type == _types.OpType.RECV_INITIAL_METADATA: - translated_op = cygrpc.operation_receive_initial_metadata( - op.flags) - elif op.type == _types.OpType.RECV_MESSAGE: - translated_op = cygrpc.operation_receive_message(op.flags) - elif op.type == _types.OpType.RECV_STATUS_ON_CLIENT: - translated_op = cygrpc.operation_receive_status_on_client( - op.flags) - elif op.type == _types.OpType.RECV_CLOSE_ON_SERVER: - translated_op = cygrpc.operation_receive_close_on_server(op.flags) - else: - raise ValueError('unexpected operation type {}'.format(op.type)) - translated_ops.append(translated_op) - return self.call.start_batch(cygrpc.Operations(translated_ops), tag) - - def cancel(self, code=None, details=None): - if code is None and details is None: - return self.call.cancel() - else: - return self.call.cancel(code, details) - - def peer(self): - return self.call.peer() - - def set_credentials(self, creds): - return self.call.set_credentials(creds) - - -class Channel(_types.Channel): - - def __init__(self, target, args, creds=None): - args = list(args) + [ - (cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT)] - args = cygrpc.ChannelArgs( - cygrpc.ChannelArg(key, value) for key, value in args) - if creds is None: - self.channel = cygrpc.Channel(target, args) - else: - self.channel = cygrpc.Channel(target, args, creds) - - def create_call(self, completion_queue, method, host, deadline=None): - internal_call = self.channel.create_call( - None, 0, completion_queue.completion_queue, method, host, - cygrpc.Timespec(deadline)) - return Call(internal_call) - - def check_connectivity_state(self, try_to_connect): - return self.channel.check_connectivity_state(try_to_connect) - - def watch_connectivity_state(self, last_observed_state, deadline, - completion_queue, tag): - self.channel.watch_connectivity_state( - last_observed_state, cygrpc.Timespec(deadline), - completion_queue.completion_queue, tag) - - def target(self): - return self.channel.target() - - -_NO_TAG = object() - -class Server(_types.Server): - - def __init__(self, completion_queue, args): - args = cygrpc.ChannelArgs( - cygrpc.ChannelArg(key, value) for key, value in args) - self.server = cygrpc.Server(args) - self.server.register_completion_queue(completion_queue.completion_queue) - self.server_queue = completion_queue - - def add_http2_port(self, addr, creds=None): - if creds is None: - return self.server.add_http2_port(addr) - else: - return self.server.add_http2_port(addr, creds) - - def start(self): - return self.server.start() - - def shutdown(self, tag=None): - return self.server.shutdown(self.server_queue.completion_queue, tag) - - def request_call(self, completion_queue, tag): - return self.server.request_call(completion_queue.completion_queue, - self.server_queue.completion_queue, tag) - - def cancel_all_calls(self): - return self.server.cancel_all_calls() diff --git a/src/python/grpcio/grpc/_adapter/_types.py b/src/python/grpcio/grpc/_adapter/_types.py deleted file mode 100644 index b7cc6fbbb5..0000000000 --- a/src/python/grpcio/grpc/_adapter/_types.py +++ /dev/null @@ -1,446 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import abc -import collections -import enum - -import six - -from grpc._cython import cygrpc - - -class GrpcChannelArgumentKeys(enum.Enum): - """Mirrors keys used in grpc_channel_args for GRPC-specific arguments.""" - SSL_TARGET_NAME_OVERRIDE = 'grpc.ssl_target_name_override' - - -@enum.unique -class CallError(enum.IntEnum): - """Mirrors grpc_call_error in the C core.""" - OK = cygrpc.CallError.ok - ERROR = cygrpc.CallError.error - ERROR_NOT_ON_SERVER = cygrpc.CallError.not_on_server - ERROR_NOT_ON_CLIENT = cygrpc.CallError.not_on_client - ERROR_ALREADY_ACCEPTED = cygrpc.CallError.already_accepted - ERROR_ALREADY_INVOKED = cygrpc.CallError.already_invoked - ERROR_NOT_INVOKED = cygrpc.CallError.not_invoked - ERROR_ALREADY_FINISHED = cygrpc.CallError.already_finished - ERROR_TOO_MANY_OPERATIONS = cygrpc.CallError.too_many_operations - ERROR_INVALID_FLAGS = cygrpc.CallError.invalid_flags - ERROR_INVALID_METADATA = cygrpc.CallError.invalid_metadata - - -@enum.unique -class StatusCode(enum.IntEnum): - """Mirrors grpc_status_code in the C core.""" - OK = cygrpc.StatusCode.ok - CANCELLED = cygrpc.StatusCode.cancelled - UNKNOWN = cygrpc.StatusCode.unknown - INVALID_ARGUMENT = cygrpc.StatusCode.invalid_argument - DEADLINE_EXCEEDED = cygrpc.StatusCode.deadline_exceeded - NOT_FOUND = cygrpc.StatusCode.not_found - ALREADY_EXISTS = cygrpc.StatusCode.already_exists - PERMISSION_DENIED = cygrpc.StatusCode.permission_denied - RESOURCE_EXHAUSTED = cygrpc.StatusCode.resource_exhausted - FAILED_PRECONDITION = cygrpc.StatusCode.failed_precondition - ABORTED = cygrpc.StatusCode.aborted - OUT_OF_RANGE = cygrpc.StatusCode.out_of_range - UNIMPLEMENTED = cygrpc.StatusCode.unimplemented - INTERNAL = cygrpc.StatusCode.internal - UNAVAILABLE = cygrpc.StatusCode.unavailable - DATA_LOSS = cygrpc.StatusCode.data_loss - UNAUTHENTICATED = cygrpc.StatusCode.unauthenticated - - -@enum.unique -class OpWriteFlags(enum.IntEnum): - """Mirrors defined write-flag constants in the C core.""" - WRITE_BUFFER_HINT = cygrpc.WriteFlag.buffer_hint - WRITE_NO_COMPRESS = cygrpc.WriteFlag.no_compress - - -@enum.unique -class OpType(enum.IntEnum): - """Mirrors grpc_op_type in the C core.""" - SEND_INITIAL_METADATA = cygrpc.OperationType.send_initial_metadata - SEND_MESSAGE = cygrpc.OperationType.send_message - SEND_CLOSE_FROM_CLIENT = cygrpc.OperationType.send_close_from_client - SEND_STATUS_FROM_SERVER = cygrpc.OperationType.send_status_from_server - RECV_INITIAL_METADATA = cygrpc.OperationType.receive_initial_metadata - RECV_MESSAGE = cygrpc.OperationType.receive_message - RECV_STATUS_ON_CLIENT = cygrpc.OperationType.receive_status_on_client - RECV_CLOSE_ON_SERVER = cygrpc.OperationType.receive_close_on_server - - -@enum.unique -class EventType(enum.IntEnum): - """Mirrors grpc_completion_type in the C core.""" - QUEUE_SHUTDOWN = cygrpc.CompletionType.queue_shutdown - QUEUE_TIMEOUT = cygrpc.CompletionType.queue_timeout - OP_COMPLETE = cygrpc.CompletionType.operation_complete - - -@enum.unique -class ConnectivityState(enum.IntEnum): - """Mirrors grpc_connectivity_state in the C core.""" - IDLE = cygrpc.ConnectivityState.idle - CONNECTING = cygrpc.ConnectivityState.connecting - READY = cygrpc.ConnectivityState.ready - TRANSIENT_FAILURE = cygrpc.ConnectivityState.transient_failure - FATAL_FAILURE = cygrpc.ConnectivityState.shutdown - - -class Status(collections.namedtuple( - 'Status', [ - 'code', - 'details', - ])): - """The end status of a GRPC call. - - Attributes: - code (StatusCode): ... - details (str): ... - """ - - -class CallDetails(collections.namedtuple( - 'CallDetails', [ - 'method', - 'host', - 'deadline', - ])): - """Provides information to the server about the client's call. - - Attributes: - method (str): ... - host (str): ... - deadline (float): ... - """ - - -class OpArgs(collections.namedtuple( - 'OpArgs', [ - 'type', - 'initial_metadata', - 'trailing_metadata', - 'message', - 'status', - 'flags', - ])): - """Arguments passed into a GRPC operation. - - Attributes: - type (OpType): ... - initial_metadata (sequence of 2-sequence of str): Only valid if type == - OpType.SEND_INITIAL_METADATA, else is None. - trailing_metadata (sequence of 2-sequence of str): Only valid if type == - OpType.SEND_STATUS_FROM_SERVER, else is None. - message (bytes): Only valid if type == OpType.SEND_MESSAGE, else is None. - status (Status): Only valid if type == OpType.SEND_STATUS_FROM_SERVER, else - is None. - flags (int): a bitwise OR'ing of 0 or more OpWriteFlags values. - """ - - @staticmethod - def send_initial_metadata(initial_metadata): - return OpArgs(OpType.SEND_INITIAL_METADATA, initial_metadata, None, None, None, 0) - - @staticmethod - def send_message(message, flags): - return OpArgs(OpType.SEND_MESSAGE, None, None, message, None, flags) - - @staticmethod - def send_close_from_client(): - return OpArgs(OpType.SEND_CLOSE_FROM_CLIENT, None, None, None, None, 0) - - @staticmethod - def send_status_from_server(trailing_metadata, status_code, status_details): - return OpArgs(OpType.SEND_STATUS_FROM_SERVER, None, trailing_metadata, None, Status(status_code, status_details), 0) - - @staticmethod - def recv_initial_metadata(): - return OpArgs(OpType.RECV_INITIAL_METADATA, None, None, None, None, 0); - - @staticmethod - def recv_message(): - return OpArgs(OpType.RECV_MESSAGE, None, None, None, None, 0) - - @staticmethod - def recv_status_on_client(): - return OpArgs(OpType.RECV_STATUS_ON_CLIENT, None, None, None, None, 0) - - @staticmethod - def recv_close_on_server(): - return OpArgs(OpType.RECV_CLOSE_ON_SERVER, None, None, None, None, 0) - - -class OpResult(collections.namedtuple( - 'OpResult', [ - 'type', - 'initial_metadata', - 'trailing_metadata', - 'message', - 'status', - 'cancelled', - ])): - """Results received from a GRPC operation. - - Attributes: - type (OpType): ... - initial_metadata (sequence of 2-sequence of str): Only valid if type == - OpType.RECV_INITIAL_METADATA, else is None. - trailing_metadata (sequence of 2-sequence of str): Only valid if type == - OpType.RECV_STATUS_ON_CLIENT, else is None. - message (bytes): Only valid if type == OpType.RECV_MESSAGE, else is None. - status (Status): Only valid if type == OpType.RECV_STATUS_ON_CLIENT, else - is None. - cancelled (bool): Only valid if type == OpType.RECV_CLOSE_ON_SERVER, else - is None. - """ - - -class Event(collections.namedtuple( - 'Event', [ - 'type', - 'tag', - 'call', - 'call_details', - 'results', - 'success', - ])): - """An event received from a GRPC completion queue. - - Attributes: - type (EventType): ... - tag (object): ... - call (Call): The Call object associated with this event (if there is one, - else None). - call_details (CallDetails): The call details associated with the - server-side call (if there is such information, else None). - results (list of OpResult): ... - success (bool): ... - """ - - -class CompletionQueue(six.with_metaclass(abc.ABCMeta)): - - @abc.abstractmethod - def __init__(self): - pass - - def __iter__(self): - """This class may be iterated over. - - This is the equivalent of calling next() repeatedly with an absolute - deadline of None (i.e. no deadline). - """ - return self - - def __next__(self): - return self.next() - - @abc.abstractmethod - def next(self, deadline=float('+inf')): - """Get the next event on this completion queue. - - Args: - deadline (float): absolute deadline in seconds from the Python epoch, or - None for no deadline. - - Returns: - Event: ... - """ - pass - - @abc.abstractmethod - def shutdown(self): - """Begin the shutdown process of this completion queue. - - Note that this does not immediately destroy the completion queue. - Nevertheless, user code should not pass it around after invoking this. - """ - return None - - -class Call(six.with_metaclass(abc.ABCMeta)): - - @abc.abstractmethod - def start_batch(self, ops, tag): - """Start a batch of operations. - - Args: - ops (sequence of OpArgs): ... - tag (object): ... - - Returns: - CallError: ... - """ - return CallError.ERROR - - @abc.abstractmethod - def cancel(self, code=None, details=None): - """Cancel the call. - - Args: - code (int): Status code to cancel with (on the server side). If - specified, so must `details`. - details (str): Status details to cancel with (on the server side). If - specified, so must `code`. - - Returns: - CallError: ... - """ - return CallError.ERROR - - @abc.abstractmethod - def peer(self): - """Get the peer of this call. - - Returns: - str: the peer of this call. - """ - return None - - def set_credentials(self, creds): - """Set per-call credentials. - - Args: - creds (CallCredentials): Credentials to be set for this call. - """ - return None - - -class Channel(six.with_metaclass(abc.ABCMeta)): - - @abc.abstractmethod - def __init__(self, target, args, credentials=None): - """Initialize a Channel. - - Args: - target (str): ... - args (sequence of 2-sequence of str, (str|integer)): ... - credentials (ChannelCredentials): If None, create an insecure channel, - else create a secure channel using the client credentials. - """ - - @abc.abstractmethod - def create_call(self, completion_queue, method, host, deadline=float('+inf')): - """Create a call from this channel. - - Args: - completion_queue (CompletionQueue): ... - method (str): ... - host (str): ... - deadline (float): absolute deadline in seconds from the Python epoch, or - None for no deadline. - - Returns: - Call: call object associated with this Channel and passed parameters. - """ - return None - - @abc.abstractmethod - def check_connectivity_state(self, try_to_connect): - """Check and optionally repair the connectivity state of the channel. - - Args: - try_to_connect (bool): whether or not to try to connect the channel if - disconnected. - - Returns: - ConnectivityState: state of the channel at the time of this invocation. - """ - return None - - @abc.abstractmethod - def watch_connectivity_state(self, last_observed_state, deadline, - completion_queue, tag): - """Watch for connectivity state changes from the last_observed_state. - - Args: - last_observed_state (ConnectivityState): ... - deadline (float): ... - completion_queue (CompletionQueue): ... - tag (object) ... - """ - - @abc.abstractmethod - def target(self): - """Get the target of this channel. - - Returns: - str: the target of this channel. - """ - return None - - -class Server(six.with_metaclass(abc.ABCMeta)): - - @abc.abstractmethod - def __init__(self, completion_queue, args): - """Initialize a server. - - Args: - completion_queue (CompletionQueue): ... - args (sequence of 2-sequence of str, (str|integer)): ... - """ - - @abc.abstractmethod - def add_http2_port(self, address, credentials=None): - """Adds an HTTP/2 address+port to the server. - - Args: - address (str): ... - credentials (ServerCredentials): If None, create an insecure port, else - create a secure port using the server credentials. - """ - - @abc.abstractmethod - def start(self): - """Starts the server.""" - - @abc.abstractmethod - def shutdown(self, tag=None): - """Shuts down the server. Does not immediately destroy the server. - - Args: - tag (object): if not None, have the server place an event on its - completion queue notifying it when this server has completely shut down. - """ - - @abc.abstractmethod - def request_call(self, completion_queue, tag): - """Requests a call from the server on the server's completion queue. - - Args: - completion_queue (CompletionQueue): Completion queue for the call. May be - the same as the server's completion queue. - tag (object) ... - """ diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index a89b501303..3117dd1cb3 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -195,7 +195,8 @@ def _consume_request_iterator( cygrpc.operation_send_message( serialized_request, _EMPTY_FLAGS), ) - call.start_batch(cygrpc.Operations(operations), event_handler) + call.start_client_batch(cygrpc.Operations(operations), + event_handler) state.due.add(cygrpc.OperationType.send_message) while True: state.condition.wait() @@ -211,7 +212,7 @@ def _consume_request_iterator( operations = ( cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), ) - call.start_batch(cygrpc.Operations(operations), event_handler) + call.start_client_batch(cygrpc.Operations(operations), event_handler) state.due.add(cygrpc.OperationType.send_close_from_client) def stop_consumption_thread(timeout): @@ -312,7 +313,7 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): if self._state.code is None: event_handler = _event_handler( self._state, self._call, self._response_deserializer) - self._call.start_batch( + self._call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), event_handler) @@ -352,12 +353,12 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): else: return max(self._deadline - time.time(), 0) - def add_cancellation_callback(self, callback): + def add_callback(self, callback): with self._state.condition: if self._state.callbacks is None: return False else: - self._state.callbacks.append(lambda unused_future: callback()) + self._state.callbacks.append(lambda: callback()) return True def initial_metadata(self): @@ -471,7 +472,7 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): None, 0, completion_queue, self._method, None, deadline_timespec) if credentials is not None: call.set_credentials(credentials._credentials) - call.start_batch(cygrpc.Operations(operations), None) + call.start_client_batch(cygrpc.Operations(operations), None) _handle_event(completion_queue.poll(), state, self._response_deserializer) return state, deadline @@ -495,7 +496,7 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: - call.start_batch(cygrpc.Operations(operations), event_handler) + call.start_client_batch(cygrpc.Operations(operations), event_handler) return _Rendezvous(state, call, self._response_deserializer, deadline) @@ -523,7 +524,7 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: - call.start_batch( + call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), event_handler) @@ -534,7 +535,7 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), ) - call.start_batch(cygrpc.Operations(operations), event_handler) + call.start_client_batch(cygrpc.Operations(operations), event_handler) return _Rendezvous(state, call, self._response_deserializer, deadline) @@ -558,7 +559,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): if credentials is not None: call.set_credentials(credentials._credentials) with state.condition: - call.start_batch( + call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), None) @@ -568,7 +569,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), ) - call.start_batch(cygrpc.Operations(operations), None) + call.start_client_batch(cygrpc.Operations(operations), None) _consume_request_iterator( request_iterator, state, call, self._request_serializer) while True: @@ -602,7 +603,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: - call.start_batch( + call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), event_handler) @@ -612,7 +613,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), ) - call.start_batch(cygrpc.Operations(operations), event_handler) + call.start_client_batch(cygrpc.Operations(operations), event_handler) _consume_request_iterator( request_iterator, state, call, self._request_serializer) return _Rendezvous(state, call, self._response_deserializer, deadline) @@ -639,7 +640,7 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: - call.start_batch( + call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), event_handler) @@ -648,7 +649,7 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), ) - call.start_batch(cygrpc.Operations(operations), event_handler) + call.start_client_batch(cygrpc.Operations(operations), event_handler) _consume_request_iterator( request_iterator, state, call, self._request_serializer) return _Rendezvous(state, call, self._response_deserializer, deadline) diff --git a/src/python/grpcio/grpc/framework/interfaces/links/utilities.py b/src/python/grpcio/grpc/_credential_composition.py index 6e4fd76d93..9cb5508e27 100644 --- a/src/python/grpcio/grpc/framework/interfaces/links/utilities.py +++ b/src/python/grpcio/grpc/_credential_composition.py @@ -1,4 +1,4 @@ -# Copyright 2015, Google Inc. +# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,18 +27,22 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Utilities provided as part of the links interface.""" +from grpc._cython import cygrpc -from grpc.framework.interfaces.links import links +def _call(call_credentialses): + call_credentials_iterator = iter(call_credentialses) + composition = next(call_credentials_iterator) + for additional_call_credentials in call_credentials_iterator: + composition = cygrpc.call_credentials_composite( + composition, additional_call_credentials) + return composition -class _NullLink(links.Link): - """A do-nothing links.Link.""" - def accept_ticket(self, ticket): - pass +def call(call_credentialses): + return _call(call_credentialses) - def join_link(self, link): - pass -NULL_LINK = _NullLink() +def channel(channel_credentials, call_credentialses): + return cygrpc.channel_credentials_composite( + channel_credentials, _call(call_credentialses)) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi index a09bbc75fe..ba60986143 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi @@ -37,13 +37,16 @@ cdef class Call: self.c_call = NULL self.references = [] - def start_batch(self, operations, tag): + def _start_batch(self, operations, tag, retain_self): if not self.is_valid: raise ValueError("invalid call object cannot be used from Python") cdef grpc_call_error result cdef Operations cy_operations = Operations(operations) cdef OperationTag operation_tag = OperationTag(tag) - operation_tag.operation_call = self + if retain_self: + operation_tag.operation_call = self + else: + operation_tag.operation_call = None operation_tag.batch_operations = cy_operations cpython.Py_INCREF(operation_tag) with nogil: @@ -52,6 +55,14 @@ cdef class Call: <cpython.PyObject *>operation_tag, NULL) return result + def start_client_batch(self, operations, tag): + # We don't reference this call in the operations tag because + # it should be cancelled when it goes out of scope + return self._start_batch(operations, tag, False) + + def start_server_batch(self, operations, tag): + return self._start_batch(operations, tag, True) + def cancel( self, grpc_status_code error_code=GRPC_STATUS__DO_NOT_USE, details=None): @@ -94,8 +105,7 @@ cdef class Call: def __dealloc__(self): if self.c_call != NULL: - with nogil: - grpc_call_destroy(self.c_call) + grpc_call_destroy(self.c_call) # The object *should* always be valid from Python. Used for debugging. @property diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi index 1406696510..5416401431 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi @@ -102,5 +102,4 @@ cdef class Channel: def __dealloc__(self): if self.c_channel != NULL: - with nogil: - grpc_channel_destroy(self.c_channel) + grpc_channel_destroy(self.c_channel) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi index 90266516fe..5955021ceb 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi @@ -118,18 +118,14 @@ cdef class CompletionQueue: def __dealloc__(self): cdef gpr_timespec c_deadline - with nogil: - c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME) + c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME) if self.c_completion_queue != NULL: # Ensure shutdown if not self.is_shutting_down: - with nogil: - grpc_completion_queue_shutdown(self.c_completion_queue) - # Pump the queue + grpc_completion_queue_shutdown(self.c_completion_queue) + # Pump the queue (All outstanding calls should have been cancelled) while not self.is_shutdown: - with nogil: - event = grpc_completion_queue_next( - self.c_completion_queue, c_deadline, NULL) + event = grpc_completion_queue_next( + self.c_completion_queue, c_deadline, NULL) self._interpret_event(event) - with nogil: - grpc_completion_queue_destroy(self.c_completion_queue) + grpc_completion_queue_destroy(self.c_completion_queue) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi index b24e69243e..035ac49a8b 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi @@ -46,8 +46,7 @@ cdef class ChannelCredentials: def __dealloc__(self): if self.c_credentials != NULL: - with nogil: - grpc_channel_credentials_release(self.c_credentials) + grpc_channel_credentials_release(self.c_credentials) cdef class CallCredentials: @@ -64,8 +63,7 @@ cdef class CallCredentials: def __dealloc__(self): if self.c_credentials != NULL: - with nogil: - grpc_call_credentials_release(self.c_credentials) + grpc_call_credentials_release(self.c_credentials) cdef class ServerCredentials: @@ -76,8 +74,7 @@ cdef class ServerCredentials: def __dealloc__(self): if self.c_credentials != NULL: - with nogil: - grpc_server_credentials_release(self.c_credentials) + grpc_server_credentials_release(self.c_credentials) cdef class CredentialsMetadataPlugin: diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 7714504d1b..42fced6545 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -30,19 +30,29 @@ cimport libc.time -cdef extern from "grpc/_cython/loader.h": +# Typedef types with approximately the same semantics to provide their names to +# Cython +ctypedef int int32_t +ctypedef unsigned uint32_t +ctypedef long int64_t - ctypedef int int32_t - ctypedef unsigned uint32_t - ctypedef long int64_t - int pygrpc_load_core(char*) - int pygrpc_initialize_core() +cdef extern from "grpc/support/alloc.h": void *gpr_malloc(size_t size) nogil void gpr_free(void *ptr) nogil void *gpr_realloc(void *p, size_t size) nogil + +cdef extern from "grpc/byte_buffer_reader.h": + + struct grpc_byte_buffer_reader: + # We don't care about the internals + pass + + +cdef extern from "grpc/grpc.h": + ctypedef struct gpr_slice: # don't worry about writing out the members of gpr_slice; we never access # them directly. @@ -86,7 +96,22 @@ cdef extern from "grpc/_cython/loader.h": gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) nogil int gpr_time_cmp(gpr_timespec a, gpr_timespec b) nogil - + + ctypedef struct grpc_byte_buffer: + # We don't care about the internals. + pass + + grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices, + size_t nslices) nogil + size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) nogil + void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer) nogil + + int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, + grpc_byte_buffer *buffer) nogil + int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, + gpr_slice *slice) nogil + void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) nogil + ctypedef enum grpc_status_code: GRPC_STATUS_OK GRPC_STATUS_CANCELLED @@ -107,37 +132,6 @@ cdef extern from "grpc/_cython/loader.h": GRPC_STATUS_DATA_LOSS GRPC_STATUS__DO_NOT_USE - ctypedef enum grpc_ssl_roots_override_result: - GRPC_SSL_ROOTS_OVERRIDE_OK - GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY - GRPC_SSL_ROOTS_OVERRIDE_FAILED - - ctypedef enum grpc_ssl_client_certificate_request_type: - GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, - GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY - GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY - GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY - GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY - - struct grpc_byte_buffer_reader: - # We don't care about the internals - pass - - ctypedef struct grpc_byte_buffer: - # We don't care about the internals. - pass - - grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices, - size_t nslices) nogil - size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) nogil - void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer) nogil - - int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, - grpc_byte_buffer *buffer) nogil - int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, - gpr_slice *slice) nogil - void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) nogil - const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING const char *GRPC_ARG_ENABLE_CENSUS const char *GRPC_ARG_MAX_CONCURRENT_STREAMS @@ -353,6 +347,21 @@ cdef extern from "grpc/_cython/loader.h": void grpc_server_cancel_all_calls(grpc_server *server) nogil void grpc_server_destroy(grpc_server *server) nogil + +cdef extern from "grpc/grpc_security.h": + + ctypedef enum grpc_ssl_roots_override_result: + GRPC_SSL_ROOTS_OVERRIDE_OK + GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY + GRPC_SSL_ROOTS_OVERRIDE_FAILED + + ctypedef enum grpc_ssl_client_certificate_request_type: + GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, + GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY + GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY + GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY + GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY + ctypedef struct grpc_ssl_pem_key_cert_pair: const char *private_key const char *certificate_chain "cert_chain" @@ -438,6 +447,9 @@ cdef extern from "grpc/_cython/loader.h": grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved) nogil + +cdef extern from "grpc/compression.h": + ctypedef enum grpc_compression_algorithm: GRPC_COMPRESS_NONE GRPC_COMPRESS_DEFLATE @@ -472,3 +484,4 @@ cdef extern from "grpc/_cython/loader.h": int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm) nogil + diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi index 0474697af8..96c5b02bc2 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi @@ -58,14 +58,14 @@ cdef class Event: cdef readonly bint success cdef readonly object tag - # For operations with calls - cdef readonly Call operation_call - # For Server.request_call cdef readonly bint is_new_request cdef readonly CallDetails request_call_details cdef readonly Metadata request_metadata + # For server calls + cdef readonly Call operation_call + # For Call.start_batch cdef readonly Operations batch_operations diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi index b39b2f08de..54b3d00dfc 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi @@ -287,8 +287,7 @@ cdef class ByteBuffer: def __dealloc__(self): if self.c_byte_buffer != NULL: - with nogil: - grpc_byte_buffer_destroy(self.c_byte_buffer) + grpc_byte_buffer_destroy(self.c_byte_buffer) cdef class SslPemKeyCertPair: @@ -420,8 +419,7 @@ cdef class Metadata: # this frees the allocated memory for the grpc_metadata_array (although # it'd be nice if that were documented somewhere...) # TODO(atash): document this in the C core - with nogil: - grpc_metadata_array_destroy(&self.c_metadata_array) + grpc_metadata_array_destroy(&self.c_metadata_array) def __len__(self): return self.c_metadata_array.count @@ -530,8 +528,7 @@ cdef class Operation: # Python. The remaining one(s) are primitive fields filled in by GRPC core. # This means that we need to clean up after receive_status_on_client. if self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT: - with nogil: - gpr_free(self._received_status_details) + gpr_free(self._received_status_details) def operation_send_initial_metadata(Metadata metadata, int flags): cdef Operation op = Operation() diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi index 3e03b6efe1..4f2d51b03f 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi @@ -171,5 +171,4 @@ cdef class Server: # much but repeatedly release the GIL and wait while not self.is_shutdown: time.sleep(0) - with nogil: - grpc_server_destroy(self.c_server) + grpc_server_destroy(self.c_server) diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx index 7a8d0dd8a1..a9520b9c0f 100644 --- a/src/python/grpcio/grpc/_cython/cygrpc.pyx +++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx @@ -49,18 +49,18 @@ include "grpc/_cython/_cygrpc/server.pyx.pxi" # -def _initialize(): - if 'win32' in sys.platform: - filename = pkg_resources.resource_filename( - 'grpc._cython', '_windows/grpc_c.64.python') - if not isinstance(filename, bytes): - filename = filename.encode() - if not pygrpc_load_core(filename): - raise ImportError('failed to load core gRPC library') - if not pygrpc_initialize_core(): - raise ImportError('failed to initialize core gRPC library') +cdef extern from "Python.h": + + int Py_AtExit(void(*func)()) + +def _initialize(): + grpc_init() grpc_set_ssl_roots_override_callback( <grpc_ssl_roots_override_callback>ssl_roots_override_callback) + if Py_AtExit(grpc_shutdown) != 0: + raise ImportError('failed to register gRPC library shutdown callbacks') + + _initialize() diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c deleted file mode 100644 index d78ec2f66e..0000000000 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <grpc/support/port_platform.h> - -#include "imports.generated.h" - -#ifdef GPR_WINDOWS - -census_initialize_type census_initialize_import; -census_shutdown_type census_shutdown_import; -census_supported_type census_supported_import; -census_enabled_type census_enabled_import; -census_context_create_type census_context_create_import; -census_context_destroy_type census_context_destroy_import; -census_context_get_status_type census_context_get_status_import; -census_context_initialize_iterator_type census_context_initialize_iterator_import; -census_context_next_tag_type census_context_next_tag_import; -census_context_get_tag_type census_context_get_tag_import; -census_context_encode_type census_context_encode_import; -census_context_decode_type census_context_decode_import; -census_trace_mask_type census_trace_mask_import; -census_set_trace_mask_type census_set_trace_mask_import; -census_start_rpc_op_timestamp_type census_start_rpc_op_timestamp_import; -census_start_client_rpc_op_type census_start_client_rpc_op_import; -census_set_rpc_client_peer_type census_set_rpc_client_peer_import; -census_start_server_rpc_op_type census_start_server_rpc_op_import; -census_start_op_type census_start_op_import; -census_end_op_type census_end_op_import; -census_trace_print_type census_trace_print_import; -census_trace_scan_start_type census_trace_scan_start_import; -census_get_trace_record_type census_get_trace_record_import; -census_trace_scan_end_type census_trace_scan_end_import; -census_record_values_type census_record_values_import; -census_view_create_type census_view_create_import; -census_view_delete_type census_view_delete_import; -census_view_metric_type census_view_metric_import; -census_view_naggregations_type census_view_naggregations_import; -census_view_tags_type census_view_tags_import; -census_view_aggregrations_type census_view_aggregrations_import; -census_view_get_data_type census_view_get_data_import; -census_view_reset_type census_view_reset_import; -grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import; -grpc_compression_algorithm_name_type grpc_compression_algorithm_name_import; -grpc_compression_algorithm_for_level_type grpc_compression_algorithm_for_level_import; -grpc_compression_options_init_type grpc_compression_options_init_import; -grpc_compression_options_enable_algorithm_type grpc_compression_options_enable_algorithm_import; -grpc_compression_options_disable_algorithm_type grpc_compression_options_disable_algorithm_import; -grpc_compression_options_is_algorithm_enabled_type grpc_compression_options_is_algorithm_enabled_import; -grpc_metadata_array_init_type grpc_metadata_array_init_import; -grpc_metadata_array_destroy_type grpc_metadata_array_destroy_import; -grpc_call_details_init_type grpc_call_details_init_import; -grpc_call_details_destroy_type grpc_call_details_destroy_import; -grpc_register_plugin_type grpc_register_plugin_import; -grpc_init_type grpc_init_import; -grpc_shutdown_type grpc_shutdown_import; -grpc_version_string_type grpc_version_string_import; -grpc_completion_queue_create_type grpc_completion_queue_create_import; -grpc_completion_queue_next_type grpc_completion_queue_next_import; -grpc_completion_queue_pluck_type grpc_completion_queue_pluck_import; -grpc_completion_queue_shutdown_type grpc_completion_queue_shutdown_import; -grpc_completion_queue_destroy_type grpc_completion_queue_destroy_import; -grpc_alarm_create_type grpc_alarm_create_import; -grpc_alarm_cancel_type grpc_alarm_cancel_import; -grpc_alarm_destroy_type grpc_alarm_destroy_import; -grpc_channel_check_connectivity_state_type grpc_channel_check_connectivity_state_import; -grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import; -grpc_channel_create_call_type grpc_channel_create_call_import; -grpc_channel_ping_type grpc_channel_ping_import; -grpc_channel_register_call_type grpc_channel_register_call_import; -grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import; -grpc_call_start_batch_type grpc_call_start_batch_import; -grpc_call_get_peer_type grpc_call_get_peer_import; -grpc_census_call_set_context_type grpc_census_call_set_context_import; -grpc_census_call_get_context_type grpc_census_call_get_context_import; -grpc_channel_get_target_type grpc_channel_get_target_import; -grpc_insecure_channel_create_type grpc_insecure_channel_create_import; -grpc_lame_client_channel_create_type grpc_lame_client_channel_create_import; -grpc_channel_destroy_type grpc_channel_destroy_import; -grpc_call_cancel_type grpc_call_cancel_import; -grpc_call_cancel_with_status_type grpc_call_cancel_with_status_import; -grpc_call_destroy_type grpc_call_destroy_import; -grpc_server_request_call_type grpc_server_request_call_import; -grpc_server_register_method_type grpc_server_register_method_import; -grpc_server_request_registered_call_type grpc_server_request_registered_call_import; -grpc_server_create_type grpc_server_create_import; -grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import; -grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import; -grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import; -grpc_server_start_type grpc_server_start_import; -grpc_server_shutdown_and_notify_type grpc_server_shutdown_and_notify_import; -grpc_server_cancel_all_calls_type grpc_server_cancel_all_calls_import; -grpc_server_destroy_type grpc_server_destroy_import; -grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import; -grpc_header_key_is_legal_type grpc_header_key_is_legal_import; -grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; -grpc_is_binary_header_type grpc_is_binary_header_import; -grpc_call_error_to_string_type grpc_call_error_to_string_import; -grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; -grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import; -grpc_use_signal_type grpc_use_signal_import; -grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; -grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; -grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; -grpc_auth_context_find_properties_by_name_type grpc_auth_context_find_properties_by_name_import; -grpc_auth_context_peer_identity_property_name_type grpc_auth_context_peer_identity_property_name_import; -grpc_auth_context_peer_is_authenticated_type grpc_auth_context_peer_is_authenticated_import; -grpc_call_auth_context_type grpc_call_auth_context_import; -grpc_auth_context_release_type grpc_auth_context_release_import; -grpc_auth_context_add_property_type grpc_auth_context_add_property_import; -grpc_auth_context_add_cstring_property_type grpc_auth_context_add_cstring_property_import; -grpc_auth_context_set_peer_identity_property_name_type grpc_auth_context_set_peer_identity_property_name_import; -grpc_channel_credentials_release_type grpc_channel_credentials_release_import; -grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import; -grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import; -grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import; -grpc_call_credentials_release_type grpc_call_credentials_release_import; -grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import; -grpc_composite_call_credentials_create_type grpc_composite_call_credentials_create_import; -grpc_google_compute_engine_credentials_create_type grpc_google_compute_engine_credentials_create_import; -grpc_max_auth_token_lifetime_type grpc_max_auth_token_lifetime_import; -grpc_service_account_jwt_access_credentials_create_type grpc_service_account_jwt_access_credentials_create_import; -grpc_google_refresh_token_credentials_create_type grpc_google_refresh_token_credentials_create_import; -grpc_access_token_credentials_create_type grpc_access_token_credentials_create_import; -grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_import; -grpc_metadata_credentials_create_from_plugin_type grpc_metadata_credentials_create_from_plugin_import; -grpc_secure_channel_create_type grpc_secure_channel_create_import; -grpc_server_credentials_release_type grpc_server_credentials_release_import; -grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import; -grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import; -grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import; -grpc_call_set_credentials_type grpc_call_set_credentials_import; -grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import; -gpr_malloc_type gpr_malloc_import; -gpr_free_type gpr_free_import; -gpr_realloc_type gpr_realloc_import; -gpr_malloc_aligned_type gpr_malloc_aligned_import; -gpr_free_aligned_type gpr_free_aligned_import; -gpr_set_allocation_functions_type gpr_set_allocation_functions_import; -gpr_get_allocation_functions_type gpr_get_allocation_functions_import; -grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; -grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; -grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import; -grpc_byte_buffer_length_type grpc_byte_buffer_length_import; -grpc_byte_buffer_destroy_type grpc_byte_buffer_destroy_import; -grpc_byte_buffer_reader_init_type grpc_byte_buffer_reader_init_import; -grpc_byte_buffer_reader_destroy_type grpc_byte_buffer_reader_destroy_import; -grpc_byte_buffer_reader_next_type grpc_byte_buffer_reader_next_import; -grpc_byte_buffer_reader_readall_type grpc_byte_buffer_reader_readall_import; -grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import; -gpr_log_type gpr_log_import; -gpr_log_message_type gpr_log_message_import; -gpr_set_log_verbosity_type gpr_set_log_verbosity_import; -gpr_log_verbosity_init_type gpr_log_verbosity_init_import; -gpr_set_log_function_type gpr_set_log_function_import; -gpr_slice_ref_type gpr_slice_ref_import; -gpr_slice_unref_type gpr_slice_unref_import; -gpr_slice_new_type gpr_slice_new_import; -gpr_slice_new_with_len_type gpr_slice_new_with_len_import; -gpr_slice_malloc_type gpr_slice_malloc_import; -gpr_slice_from_copied_string_type gpr_slice_from_copied_string_import; -gpr_slice_from_copied_buffer_type gpr_slice_from_copied_buffer_import; -gpr_slice_from_static_string_type gpr_slice_from_static_string_import; -gpr_slice_sub_type gpr_slice_sub_import; -gpr_slice_sub_no_ref_type gpr_slice_sub_no_ref_import; -gpr_slice_split_tail_type gpr_slice_split_tail_import; -gpr_slice_split_head_type gpr_slice_split_head_import; -gpr_empty_slice_type gpr_empty_slice_import; -gpr_slice_cmp_type gpr_slice_cmp_import; -gpr_slice_str_cmp_type gpr_slice_str_cmp_import; -gpr_slice_buffer_init_type gpr_slice_buffer_init_import; -gpr_slice_buffer_destroy_type gpr_slice_buffer_destroy_import; -gpr_slice_buffer_add_type gpr_slice_buffer_add_import; -gpr_slice_buffer_add_indexed_type gpr_slice_buffer_add_indexed_import; -gpr_slice_buffer_addn_type gpr_slice_buffer_addn_import; -gpr_slice_buffer_tiny_add_type gpr_slice_buffer_tiny_add_import; -gpr_slice_buffer_pop_type gpr_slice_buffer_pop_import; -gpr_slice_buffer_reset_and_unref_type gpr_slice_buffer_reset_and_unref_import; -gpr_slice_buffer_swap_type gpr_slice_buffer_swap_import; -gpr_slice_buffer_move_into_type gpr_slice_buffer_move_into_import; -gpr_slice_buffer_trim_end_type gpr_slice_buffer_trim_end_import; -gpr_slice_buffer_move_first_type gpr_slice_buffer_move_first_import; -gpr_slice_buffer_take_first_type gpr_slice_buffer_take_first_import; -gpr_mu_init_type gpr_mu_init_import; -gpr_mu_destroy_type gpr_mu_destroy_import; -gpr_mu_lock_type gpr_mu_lock_import; -gpr_mu_unlock_type gpr_mu_unlock_import; -gpr_mu_trylock_type gpr_mu_trylock_import; -gpr_cv_init_type gpr_cv_init_import; -gpr_cv_destroy_type gpr_cv_destroy_import; -gpr_cv_wait_type gpr_cv_wait_import; -gpr_cv_signal_type gpr_cv_signal_import; -gpr_cv_broadcast_type gpr_cv_broadcast_import; -gpr_once_init_type gpr_once_init_import; -gpr_event_init_type gpr_event_init_import; -gpr_event_set_type gpr_event_set_import; -gpr_event_get_type gpr_event_get_import; -gpr_event_wait_type gpr_event_wait_import; -gpr_ref_init_type gpr_ref_init_import; -gpr_ref_type gpr_ref_import; -gpr_ref_non_zero_type gpr_ref_non_zero_import; -gpr_refn_type gpr_refn_import; -gpr_unref_type gpr_unref_import; -gpr_stats_init_type gpr_stats_init_import; -gpr_stats_inc_type gpr_stats_inc_import; -gpr_stats_read_type gpr_stats_read_import; -gpr_time_0_type gpr_time_0_import; -gpr_inf_future_type gpr_inf_future_import; -gpr_inf_past_type gpr_inf_past_import; -gpr_time_init_type gpr_time_init_import; -gpr_now_type gpr_now_import; -gpr_convert_clock_type_type gpr_convert_clock_type_import; -gpr_time_cmp_type gpr_time_cmp_import; -gpr_time_max_type gpr_time_max_import; -gpr_time_min_type gpr_time_min_import; -gpr_time_add_type gpr_time_add_import; -gpr_time_sub_type gpr_time_sub_import; -gpr_time_from_micros_type gpr_time_from_micros_import; -gpr_time_from_nanos_type gpr_time_from_nanos_import; -gpr_time_from_millis_type gpr_time_from_millis_import; -gpr_time_from_seconds_type gpr_time_from_seconds_import; -gpr_time_from_minutes_type gpr_time_from_minutes_import; -gpr_time_from_hours_type gpr_time_from_hours_import; -gpr_time_to_millis_type gpr_time_to_millis_import; -gpr_time_similar_type gpr_time_similar_import; -gpr_sleep_until_type gpr_sleep_until_import; -gpr_timespec_to_micros_type gpr_timespec_to_micros_import; -gpr_avl_create_type gpr_avl_create_import; -gpr_avl_ref_type gpr_avl_ref_import; -gpr_avl_unref_type gpr_avl_unref_import; -gpr_avl_add_type gpr_avl_add_import; -gpr_avl_remove_type gpr_avl_remove_import; -gpr_avl_get_type gpr_avl_get_import; -gpr_avl_maybe_get_type gpr_avl_maybe_get_import; -gpr_avl_is_empty_type gpr_avl_is_empty_import; -gpr_cmdline_create_type gpr_cmdline_create_import; -gpr_cmdline_add_int_type gpr_cmdline_add_int_import; -gpr_cmdline_add_flag_type gpr_cmdline_add_flag_import; -gpr_cmdline_add_string_type gpr_cmdline_add_string_import; -gpr_cmdline_on_extra_arg_type gpr_cmdline_on_extra_arg_import; -gpr_cmdline_set_survive_failure_type gpr_cmdline_set_survive_failure_import; -gpr_cmdline_parse_type gpr_cmdline_parse_import; -gpr_cmdline_destroy_type gpr_cmdline_destroy_import; -gpr_cmdline_usage_string_type gpr_cmdline_usage_string_import; -gpr_cpu_num_cores_type gpr_cpu_num_cores_import; -gpr_cpu_current_cpu_type gpr_cpu_current_cpu_import; -gpr_histogram_create_type gpr_histogram_create_import; -gpr_histogram_destroy_type gpr_histogram_destroy_import; -gpr_histogram_add_type gpr_histogram_add_import; -gpr_histogram_merge_type gpr_histogram_merge_import; -gpr_histogram_percentile_type gpr_histogram_percentile_import; -gpr_histogram_mean_type gpr_histogram_mean_import; -gpr_histogram_stddev_type gpr_histogram_stddev_import; -gpr_histogram_variance_type gpr_histogram_variance_import; -gpr_histogram_maximum_type gpr_histogram_maximum_import; -gpr_histogram_minimum_type gpr_histogram_minimum_import; -gpr_histogram_count_type gpr_histogram_count_import; -gpr_histogram_sum_type gpr_histogram_sum_import; -gpr_histogram_sum_of_squares_type gpr_histogram_sum_of_squares_import; -gpr_histogram_get_contents_type gpr_histogram_get_contents_import; -gpr_histogram_merge_contents_type gpr_histogram_merge_contents_import; -gpr_join_host_port_type gpr_join_host_port_import; -gpr_split_host_port_type gpr_split_host_port_import; -gpr_format_message_type gpr_format_message_import; -gpr_strdup_type gpr_strdup_import; -gpr_asprintf_type gpr_asprintf_import; -gpr_subprocess_binary_extension_type gpr_subprocess_binary_extension_import; -gpr_subprocess_create_type gpr_subprocess_create_import; -gpr_subprocess_destroy_type gpr_subprocess_destroy_import; -gpr_subprocess_join_type gpr_subprocess_join_import; -gpr_subprocess_interrupt_type gpr_subprocess_interrupt_import; -gpr_thd_new_type gpr_thd_new_import; -gpr_thd_options_default_type gpr_thd_options_default_import; -gpr_thd_options_set_detached_type gpr_thd_options_set_detached_import; -gpr_thd_options_set_joinable_type gpr_thd_options_set_joinable_import; -gpr_thd_options_is_detached_type gpr_thd_options_is_detached_import; -gpr_thd_options_is_joinable_type gpr_thd_options_is_joinable_import; -gpr_thd_currentid_type gpr_thd_currentid_import; -gpr_thd_join_type gpr_thd_join_import; - -#ifdef __cplusplus -extern "C" { -#endif /* __cpluslus */ - -void pygrpc_load_imports(HMODULE library) { - census_initialize_import = (census_initialize_type) GetProcAddress(library, "census_initialize"); - census_shutdown_import = (census_shutdown_type) GetProcAddress(library, "census_shutdown"); - census_supported_import = (census_supported_type) GetProcAddress(library, "census_supported"); - census_enabled_import = (census_enabled_type) GetProcAddress(library, "census_enabled"); - census_context_create_import = (census_context_create_type) GetProcAddress(library, "census_context_create"); - census_context_destroy_import = (census_context_destroy_type) GetProcAddress(library, "census_context_destroy"); - census_context_get_status_import = (census_context_get_status_type) GetProcAddress(library, "census_context_get_status"); - census_context_initialize_iterator_import = (census_context_initialize_iterator_type) GetProcAddress(library, "census_context_initialize_iterator"); - census_context_next_tag_import = (census_context_next_tag_type) GetProcAddress(library, "census_context_next_tag"); - census_context_get_tag_import = (census_context_get_tag_type) GetProcAddress(library, "census_context_get_tag"); - census_context_encode_import = (census_context_encode_type) GetProcAddress(library, "census_context_encode"); - census_context_decode_import = (census_context_decode_type) GetProcAddress(library, "census_context_decode"); - census_trace_mask_import = (census_trace_mask_type) GetProcAddress(library, "census_trace_mask"); - census_set_trace_mask_import = (census_set_trace_mask_type) GetProcAddress(library, "census_set_trace_mask"); - census_start_rpc_op_timestamp_import = (census_start_rpc_op_timestamp_type) GetProcAddress(library, "census_start_rpc_op_timestamp"); - census_start_client_rpc_op_import = (census_start_client_rpc_op_type) GetProcAddress(library, "census_start_client_rpc_op"); - census_set_rpc_client_peer_import = (census_set_rpc_client_peer_type) GetProcAddress(library, "census_set_rpc_client_peer"); - census_start_server_rpc_op_import = (census_start_server_rpc_op_type) GetProcAddress(library, "census_start_server_rpc_op"); - census_start_op_import = (census_start_op_type) GetProcAddress(library, "census_start_op"); - census_end_op_import = (census_end_op_type) GetProcAddress(library, "census_end_op"); - census_trace_print_import = (census_trace_print_type) GetProcAddress(library, "census_trace_print"); - census_trace_scan_start_import = (census_trace_scan_start_type) GetProcAddress(library, "census_trace_scan_start"); - census_get_trace_record_import = (census_get_trace_record_type) GetProcAddress(library, "census_get_trace_record"); - census_trace_scan_end_import = (census_trace_scan_end_type) GetProcAddress(library, "census_trace_scan_end"); - census_record_values_import = (census_record_values_type) GetProcAddress(library, "census_record_values"); - census_view_create_import = (census_view_create_type) GetProcAddress(library, "census_view_create"); - census_view_delete_import = (census_view_delete_type) GetProcAddress(library, "census_view_delete"); - census_view_metric_import = (census_view_metric_type) GetProcAddress(library, "census_view_metric"); - census_view_naggregations_import = (census_view_naggregations_type) GetProcAddress(library, "census_view_naggregations"); - census_view_tags_import = (census_view_tags_type) GetProcAddress(library, "census_view_tags"); - census_view_aggregrations_import = (census_view_aggregrations_type) GetProcAddress(library, "census_view_aggregrations"); - census_view_get_data_import = (census_view_get_data_type) GetProcAddress(library, "census_view_get_data"); - census_view_reset_import = (census_view_reset_type) GetProcAddress(library, "census_view_reset"); - grpc_compression_algorithm_parse_import = (grpc_compression_algorithm_parse_type) GetProcAddress(library, "grpc_compression_algorithm_parse"); - grpc_compression_algorithm_name_import = (grpc_compression_algorithm_name_type) GetProcAddress(library, "grpc_compression_algorithm_name"); - grpc_compression_algorithm_for_level_import = (grpc_compression_algorithm_for_level_type) GetProcAddress(library, "grpc_compression_algorithm_for_level"); - grpc_compression_options_init_import = (grpc_compression_options_init_type) GetProcAddress(library, "grpc_compression_options_init"); - grpc_compression_options_enable_algorithm_import = (grpc_compression_options_enable_algorithm_type) GetProcAddress(library, "grpc_compression_options_enable_algorithm"); - grpc_compression_options_disable_algorithm_import = (grpc_compression_options_disable_algorithm_type) GetProcAddress(library, "grpc_compression_options_disable_algorithm"); - grpc_compression_options_is_algorithm_enabled_import = (grpc_compression_options_is_algorithm_enabled_type) GetProcAddress(library, "grpc_compression_options_is_algorithm_enabled"); - grpc_metadata_array_init_import = (grpc_metadata_array_init_type) GetProcAddress(library, "grpc_metadata_array_init"); - grpc_metadata_array_destroy_import = (grpc_metadata_array_destroy_type) GetProcAddress(library, "grpc_metadata_array_destroy"); - grpc_call_details_init_import = (grpc_call_details_init_type) GetProcAddress(library, "grpc_call_details_init"); - grpc_call_details_destroy_import = (grpc_call_details_destroy_type) GetProcAddress(library, "grpc_call_details_destroy"); - grpc_register_plugin_import = (grpc_register_plugin_type) GetProcAddress(library, "grpc_register_plugin"); - grpc_init_import = (grpc_init_type) GetProcAddress(library, "grpc_init"); - grpc_shutdown_import = (grpc_shutdown_type) GetProcAddress(library, "grpc_shutdown"); - grpc_version_string_import = (grpc_version_string_type) GetProcAddress(library, "grpc_version_string"); - grpc_completion_queue_create_import = (grpc_completion_queue_create_type) GetProcAddress(library, "grpc_completion_queue_create"); - grpc_completion_queue_next_import = (grpc_completion_queue_next_type) GetProcAddress(library, "grpc_completion_queue_next"); - grpc_completion_queue_pluck_import = (grpc_completion_queue_pluck_type) GetProcAddress(library, "grpc_completion_queue_pluck"); - grpc_completion_queue_shutdown_import = (grpc_completion_queue_shutdown_type) GetProcAddress(library, "grpc_completion_queue_shutdown"); - grpc_completion_queue_destroy_import = (grpc_completion_queue_destroy_type) GetProcAddress(library, "grpc_completion_queue_destroy"); - grpc_alarm_create_import = (grpc_alarm_create_type) GetProcAddress(library, "grpc_alarm_create"); - grpc_alarm_cancel_import = (grpc_alarm_cancel_type) GetProcAddress(library, "grpc_alarm_cancel"); - grpc_alarm_destroy_import = (grpc_alarm_destroy_type) GetProcAddress(library, "grpc_alarm_destroy"); - grpc_channel_check_connectivity_state_import = (grpc_channel_check_connectivity_state_type) GetProcAddress(library, "grpc_channel_check_connectivity_state"); - grpc_channel_watch_connectivity_state_import = (grpc_channel_watch_connectivity_state_type) GetProcAddress(library, "grpc_channel_watch_connectivity_state"); - grpc_channel_create_call_import = (grpc_channel_create_call_type) GetProcAddress(library, "grpc_channel_create_call"); - grpc_channel_ping_import = (grpc_channel_ping_type) GetProcAddress(library, "grpc_channel_ping"); - grpc_channel_register_call_import = (grpc_channel_register_call_type) GetProcAddress(library, "grpc_channel_register_call"); - grpc_channel_create_registered_call_import = (grpc_channel_create_registered_call_type) GetProcAddress(library, "grpc_channel_create_registered_call"); - grpc_call_start_batch_import = (grpc_call_start_batch_type) GetProcAddress(library, "grpc_call_start_batch"); - grpc_call_get_peer_import = (grpc_call_get_peer_type) GetProcAddress(library, "grpc_call_get_peer"); - grpc_census_call_set_context_import = (grpc_census_call_set_context_type) GetProcAddress(library, "grpc_census_call_set_context"); - grpc_census_call_get_context_import = (grpc_census_call_get_context_type) GetProcAddress(library, "grpc_census_call_get_context"); - grpc_channel_get_target_import = (grpc_channel_get_target_type) GetProcAddress(library, "grpc_channel_get_target"); - grpc_insecure_channel_create_import = (grpc_insecure_channel_create_type) GetProcAddress(library, "grpc_insecure_channel_create"); - grpc_lame_client_channel_create_import = (grpc_lame_client_channel_create_type) GetProcAddress(library, "grpc_lame_client_channel_create"); - grpc_channel_destroy_import = (grpc_channel_destroy_type) GetProcAddress(library, "grpc_channel_destroy"); - grpc_call_cancel_import = (grpc_call_cancel_type) GetProcAddress(library, "grpc_call_cancel"); - grpc_call_cancel_with_status_import = (grpc_call_cancel_with_status_type) GetProcAddress(library, "grpc_call_cancel_with_status"); - grpc_call_destroy_import = (grpc_call_destroy_type) GetProcAddress(library, "grpc_call_destroy"); - grpc_server_request_call_import = (grpc_server_request_call_type) GetProcAddress(library, "grpc_server_request_call"); - grpc_server_register_method_import = (grpc_server_register_method_type) GetProcAddress(library, "grpc_server_register_method"); - grpc_server_request_registered_call_import = (grpc_server_request_registered_call_type) GetProcAddress(library, "grpc_server_request_registered_call"); - grpc_server_create_import = (grpc_server_create_type) GetProcAddress(library, "grpc_server_create"); - grpc_server_register_completion_queue_import = (grpc_server_register_completion_queue_type) GetProcAddress(library, "grpc_server_register_completion_queue"); - grpc_server_register_non_listening_completion_queue_import = (grpc_server_register_non_listening_completion_queue_type) GetProcAddress(library, "grpc_server_register_non_listening_completion_queue"); - grpc_server_add_insecure_http2_port_import = (grpc_server_add_insecure_http2_port_type) GetProcAddress(library, "grpc_server_add_insecure_http2_port"); - grpc_server_start_import = (grpc_server_start_type) GetProcAddress(library, "grpc_server_start"); - grpc_server_shutdown_and_notify_import = (grpc_server_shutdown_and_notify_type) GetProcAddress(library, "grpc_server_shutdown_and_notify"); - grpc_server_cancel_all_calls_import = (grpc_server_cancel_all_calls_type) GetProcAddress(library, "grpc_server_cancel_all_calls"); - grpc_server_destroy_import = (grpc_server_destroy_type) GetProcAddress(library, "grpc_server_destroy"); - grpc_tracer_set_enabled_import = (grpc_tracer_set_enabled_type) GetProcAddress(library, "grpc_tracer_set_enabled"); - grpc_header_key_is_legal_import = (grpc_header_key_is_legal_type) GetProcAddress(library, "grpc_header_key_is_legal"); - grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); - grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); - grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); - grpc_insecure_channel_create_from_fd_import = (grpc_insecure_channel_create_from_fd_type) GetProcAddress(library, "grpc_insecure_channel_create_from_fd"); - grpc_server_add_insecure_channel_from_fd_import = (grpc_server_add_insecure_channel_from_fd_type) GetProcAddress(library, "grpc_server_add_insecure_channel_from_fd"); - grpc_use_signal_import = (grpc_use_signal_type) GetProcAddress(library, "grpc_use_signal"); - grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); - grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); - grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); - grpc_auth_context_find_properties_by_name_import = (grpc_auth_context_find_properties_by_name_type) GetProcAddress(library, "grpc_auth_context_find_properties_by_name"); - grpc_auth_context_peer_identity_property_name_import = (grpc_auth_context_peer_identity_property_name_type) GetProcAddress(library, "grpc_auth_context_peer_identity_property_name"); - grpc_auth_context_peer_is_authenticated_import = (grpc_auth_context_peer_is_authenticated_type) GetProcAddress(library, "grpc_auth_context_peer_is_authenticated"); - grpc_call_auth_context_import = (grpc_call_auth_context_type) GetProcAddress(library, "grpc_call_auth_context"); - grpc_auth_context_release_import = (grpc_auth_context_release_type) GetProcAddress(library, "grpc_auth_context_release"); - grpc_auth_context_add_property_import = (grpc_auth_context_add_property_type) GetProcAddress(library, "grpc_auth_context_add_property"); - grpc_auth_context_add_cstring_property_import = (grpc_auth_context_add_cstring_property_type) GetProcAddress(library, "grpc_auth_context_add_cstring_property"); - grpc_auth_context_set_peer_identity_property_name_import = (grpc_auth_context_set_peer_identity_property_name_type) GetProcAddress(library, "grpc_auth_context_set_peer_identity_property_name"); - grpc_channel_credentials_release_import = (grpc_channel_credentials_release_type) GetProcAddress(library, "grpc_channel_credentials_release"); - grpc_google_default_credentials_create_import = (grpc_google_default_credentials_create_type) GetProcAddress(library, "grpc_google_default_credentials_create"); - grpc_set_ssl_roots_override_callback_import = (grpc_set_ssl_roots_override_callback_type) GetProcAddress(library, "grpc_set_ssl_roots_override_callback"); - grpc_ssl_credentials_create_import = (grpc_ssl_credentials_create_type) GetProcAddress(library, "grpc_ssl_credentials_create"); - grpc_call_credentials_release_import = (grpc_call_credentials_release_type) GetProcAddress(library, "grpc_call_credentials_release"); - grpc_composite_channel_credentials_create_import = (grpc_composite_channel_credentials_create_type) GetProcAddress(library, "grpc_composite_channel_credentials_create"); - grpc_composite_call_credentials_create_import = (grpc_composite_call_credentials_create_type) GetProcAddress(library, "grpc_composite_call_credentials_create"); - grpc_google_compute_engine_credentials_create_import = (grpc_google_compute_engine_credentials_create_type) GetProcAddress(library, "grpc_google_compute_engine_credentials_create"); - grpc_max_auth_token_lifetime_import = (grpc_max_auth_token_lifetime_type) GetProcAddress(library, "grpc_max_auth_token_lifetime"); - grpc_service_account_jwt_access_credentials_create_import = (grpc_service_account_jwt_access_credentials_create_type) GetProcAddress(library, "grpc_service_account_jwt_access_credentials_create"); - grpc_google_refresh_token_credentials_create_import = (grpc_google_refresh_token_credentials_create_type) GetProcAddress(library, "grpc_google_refresh_token_credentials_create"); - grpc_access_token_credentials_create_import = (grpc_access_token_credentials_create_type) GetProcAddress(library, "grpc_access_token_credentials_create"); - grpc_google_iam_credentials_create_import = (grpc_google_iam_credentials_create_type) GetProcAddress(library, "grpc_google_iam_credentials_create"); - grpc_metadata_credentials_create_from_plugin_import = (grpc_metadata_credentials_create_from_plugin_type) GetProcAddress(library, "grpc_metadata_credentials_create_from_plugin"); - grpc_secure_channel_create_import = (grpc_secure_channel_create_type) GetProcAddress(library, "grpc_secure_channel_create"); - grpc_server_credentials_release_import = (grpc_server_credentials_release_type) GetProcAddress(library, "grpc_server_credentials_release"); - grpc_ssl_server_credentials_create_import = (grpc_ssl_server_credentials_create_type) GetProcAddress(library, "grpc_ssl_server_credentials_create"); - grpc_ssl_server_credentials_create_ex_import = (grpc_ssl_server_credentials_create_ex_type) GetProcAddress(library, "grpc_ssl_server_credentials_create_ex"); - grpc_server_add_secure_http2_port_import = (grpc_server_add_secure_http2_port_type) GetProcAddress(library, "grpc_server_add_secure_http2_port"); - grpc_call_set_credentials_import = (grpc_call_set_credentials_type) GetProcAddress(library, "grpc_call_set_credentials"); - grpc_server_credentials_set_auth_metadata_processor_import = (grpc_server_credentials_set_auth_metadata_processor_type) GetProcAddress(library, "grpc_server_credentials_set_auth_metadata_processor"); - gpr_malloc_import = (gpr_malloc_type) GetProcAddress(library, "gpr_malloc"); - gpr_free_import = (gpr_free_type) GetProcAddress(library, "gpr_free"); - gpr_realloc_import = (gpr_realloc_type) GetProcAddress(library, "gpr_realloc"); - gpr_malloc_aligned_import = (gpr_malloc_aligned_type) GetProcAddress(library, "gpr_malloc_aligned"); - gpr_free_aligned_import = (gpr_free_aligned_type) GetProcAddress(library, "gpr_free_aligned"); - gpr_set_allocation_functions_import = (gpr_set_allocation_functions_type) GetProcAddress(library, "gpr_set_allocation_functions"); - gpr_get_allocation_functions_import = (gpr_get_allocation_functions_type) GetProcAddress(library, "gpr_get_allocation_functions"); - grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create"); - grpc_raw_compressed_byte_buffer_create_import = (grpc_raw_compressed_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_compressed_byte_buffer_create"); - grpc_byte_buffer_copy_import = (grpc_byte_buffer_copy_type) GetProcAddress(library, "grpc_byte_buffer_copy"); - grpc_byte_buffer_length_import = (grpc_byte_buffer_length_type) GetProcAddress(library, "grpc_byte_buffer_length"); - grpc_byte_buffer_destroy_import = (grpc_byte_buffer_destroy_type) GetProcAddress(library, "grpc_byte_buffer_destroy"); - grpc_byte_buffer_reader_init_import = (grpc_byte_buffer_reader_init_type) GetProcAddress(library, "grpc_byte_buffer_reader_init"); - grpc_byte_buffer_reader_destroy_import = (grpc_byte_buffer_reader_destroy_type) GetProcAddress(library, "grpc_byte_buffer_reader_destroy"); - grpc_byte_buffer_reader_next_import = (grpc_byte_buffer_reader_next_type) GetProcAddress(library, "grpc_byte_buffer_reader_next"); - grpc_byte_buffer_reader_readall_import = (grpc_byte_buffer_reader_readall_type) GetProcAddress(library, "grpc_byte_buffer_reader_readall"); - grpc_raw_byte_buffer_from_reader_import = (grpc_raw_byte_buffer_from_reader_type) GetProcAddress(library, "grpc_raw_byte_buffer_from_reader"); - gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log"); - gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message"); - gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity"); - gpr_log_verbosity_init_import = (gpr_log_verbosity_init_type) GetProcAddress(library, "gpr_log_verbosity_init"); - gpr_set_log_function_import = (gpr_set_log_function_type) GetProcAddress(library, "gpr_set_log_function"); - gpr_slice_ref_import = (gpr_slice_ref_type) GetProcAddress(library, "gpr_slice_ref"); - gpr_slice_unref_import = (gpr_slice_unref_type) GetProcAddress(library, "gpr_slice_unref"); - gpr_slice_new_import = (gpr_slice_new_type) GetProcAddress(library, "gpr_slice_new"); - gpr_slice_new_with_len_import = (gpr_slice_new_with_len_type) GetProcAddress(library, "gpr_slice_new_with_len"); - gpr_slice_malloc_import = (gpr_slice_malloc_type) GetProcAddress(library, "gpr_slice_malloc"); - gpr_slice_from_copied_string_import = (gpr_slice_from_copied_string_type) GetProcAddress(library, "gpr_slice_from_copied_string"); - gpr_slice_from_copied_buffer_import = (gpr_slice_from_copied_buffer_type) GetProcAddress(library, "gpr_slice_from_copied_buffer"); - gpr_slice_from_static_string_import = (gpr_slice_from_static_string_type) GetProcAddress(library, "gpr_slice_from_static_string"); - gpr_slice_sub_import = (gpr_slice_sub_type) GetProcAddress(library, "gpr_slice_sub"); - gpr_slice_sub_no_ref_import = (gpr_slice_sub_no_ref_type) GetProcAddress(library, "gpr_slice_sub_no_ref"); - gpr_slice_split_tail_import = (gpr_slice_split_tail_type) GetProcAddress(library, "gpr_slice_split_tail"); - gpr_slice_split_head_import = (gpr_slice_split_head_type) GetProcAddress(library, "gpr_slice_split_head"); - gpr_empty_slice_import = (gpr_empty_slice_type) GetProcAddress(library, "gpr_empty_slice"); - gpr_slice_cmp_import = (gpr_slice_cmp_type) GetProcAddress(library, "gpr_slice_cmp"); - gpr_slice_str_cmp_import = (gpr_slice_str_cmp_type) GetProcAddress(library, "gpr_slice_str_cmp"); - gpr_slice_buffer_init_import = (gpr_slice_buffer_init_type) GetProcAddress(library, "gpr_slice_buffer_init"); - gpr_slice_buffer_destroy_import = (gpr_slice_buffer_destroy_type) GetProcAddress(library, "gpr_slice_buffer_destroy"); - gpr_slice_buffer_add_import = (gpr_slice_buffer_add_type) GetProcAddress(library, "gpr_slice_buffer_add"); - gpr_slice_buffer_add_indexed_import = (gpr_slice_buffer_add_indexed_type) GetProcAddress(library, "gpr_slice_buffer_add_indexed"); - gpr_slice_buffer_addn_import = (gpr_slice_buffer_addn_type) GetProcAddress(library, "gpr_slice_buffer_addn"); - gpr_slice_buffer_tiny_add_import = (gpr_slice_buffer_tiny_add_type) GetProcAddress(library, "gpr_slice_buffer_tiny_add"); - gpr_slice_buffer_pop_import = (gpr_slice_buffer_pop_type) GetProcAddress(library, "gpr_slice_buffer_pop"); - gpr_slice_buffer_reset_and_unref_import = (gpr_slice_buffer_reset_and_unref_type) GetProcAddress(library, "gpr_slice_buffer_reset_and_unref"); - gpr_slice_buffer_swap_import = (gpr_slice_buffer_swap_type) GetProcAddress(library, "gpr_slice_buffer_swap"); - gpr_slice_buffer_move_into_import = (gpr_slice_buffer_move_into_type) GetProcAddress(library, "gpr_slice_buffer_move_into"); - gpr_slice_buffer_trim_end_import = (gpr_slice_buffer_trim_end_type) GetProcAddress(library, "gpr_slice_buffer_trim_end"); - gpr_slice_buffer_move_first_import = (gpr_slice_buffer_move_first_type) GetProcAddress(library, "gpr_slice_buffer_move_first"); - gpr_slice_buffer_take_first_import = (gpr_slice_buffer_take_first_type) GetProcAddress(library, "gpr_slice_buffer_take_first"); - gpr_mu_init_import = (gpr_mu_init_type) GetProcAddress(library, "gpr_mu_init"); - gpr_mu_destroy_import = (gpr_mu_destroy_type) GetProcAddress(library, "gpr_mu_destroy"); - gpr_mu_lock_import = (gpr_mu_lock_type) GetProcAddress(library, "gpr_mu_lock"); - gpr_mu_unlock_import = (gpr_mu_unlock_type) GetProcAddress(library, "gpr_mu_unlock"); - gpr_mu_trylock_import = (gpr_mu_trylock_type) GetProcAddress(library, "gpr_mu_trylock"); - gpr_cv_init_import = (gpr_cv_init_type) GetProcAddress(library, "gpr_cv_init"); - gpr_cv_destroy_import = (gpr_cv_destroy_type) GetProcAddress(library, "gpr_cv_destroy"); - gpr_cv_wait_import = (gpr_cv_wait_type) GetProcAddress(library, "gpr_cv_wait"); - gpr_cv_signal_import = (gpr_cv_signal_type) GetProcAddress(library, "gpr_cv_signal"); - gpr_cv_broadcast_import = (gpr_cv_broadcast_type) GetProcAddress(library, "gpr_cv_broadcast"); - gpr_once_init_import = (gpr_once_init_type) GetProcAddress(library, "gpr_once_init"); - gpr_event_init_import = (gpr_event_init_type) GetProcAddress(library, "gpr_event_init"); - gpr_event_set_import = (gpr_event_set_type) GetProcAddress(library, "gpr_event_set"); - gpr_event_get_import = (gpr_event_get_type) GetProcAddress(library, "gpr_event_get"); - gpr_event_wait_import = (gpr_event_wait_type) GetProcAddress(library, "gpr_event_wait"); - gpr_ref_init_import = (gpr_ref_init_type) GetProcAddress(library, "gpr_ref_init"); - gpr_ref_import = (gpr_ref_type) GetProcAddress(library, "gpr_ref"); - gpr_ref_non_zero_import = (gpr_ref_non_zero_type) GetProcAddress(library, "gpr_ref_non_zero"); - gpr_refn_import = (gpr_refn_type) GetProcAddress(library, "gpr_refn"); - gpr_unref_import = (gpr_unref_type) GetProcAddress(library, "gpr_unref"); - gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init"); - gpr_stats_inc_import = (gpr_stats_inc_type) GetProcAddress(library, "gpr_stats_inc"); - gpr_stats_read_import = (gpr_stats_read_type) GetProcAddress(library, "gpr_stats_read"); - gpr_time_0_import = (gpr_time_0_type) GetProcAddress(library, "gpr_time_0"); - gpr_inf_future_import = (gpr_inf_future_type) GetProcAddress(library, "gpr_inf_future"); - gpr_inf_past_import = (gpr_inf_past_type) GetProcAddress(library, "gpr_inf_past"); - gpr_time_init_import = (gpr_time_init_type) GetProcAddress(library, "gpr_time_init"); - gpr_now_import = (gpr_now_type) GetProcAddress(library, "gpr_now"); - gpr_convert_clock_type_import = (gpr_convert_clock_type_type) GetProcAddress(library, "gpr_convert_clock_type"); - gpr_time_cmp_import = (gpr_time_cmp_type) GetProcAddress(library, "gpr_time_cmp"); - gpr_time_max_import = (gpr_time_max_type) GetProcAddress(library, "gpr_time_max"); - gpr_time_min_import = (gpr_time_min_type) GetProcAddress(library, "gpr_time_min"); - gpr_time_add_import = (gpr_time_add_type) GetProcAddress(library, "gpr_time_add"); - gpr_time_sub_import = (gpr_time_sub_type) GetProcAddress(library, "gpr_time_sub"); - gpr_time_from_micros_import = (gpr_time_from_micros_type) GetProcAddress(library, "gpr_time_from_micros"); - gpr_time_from_nanos_import = (gpr_time_from_nanos_type) GetProcAddress(library, "gpr_time_from_nanos"); - gpr_time_from_millis_import = (gpr_time_from_millis_type) GetProcAddress(library, "gpr_time_from_millis"); - gpr_time_from_seconds_import = (gpr_time_from_seconds_type) GetProcAddress(library, "gpr_time_from_seconds"); - gpr_time_from_minutes_import = (gpr_time_from_minutes_type) GetProcAddress(library, "gpr_time_from_minutes"); - gpr_time_from_hours_import = (gpr_time_from_hours_type) GetProcAddress(library, "gpr_time_from_hours"); - gpr_time_to_millis_import = (gpr_time_to_millis_type) GetProcAddress(library, "gpr_time_to_millis"); - gpr_time_similar_import = (gpr_time_similar_type) GetProcAddress(library, "gpr_time_similar"); - gpr_sleep_until_import = (gpr_sleep_until_type) GetProcAddress(library, "gpr_sleep_until"); - gpr_timespec_to_micros_import = (gpr_timespec_to_micros_type) GetProcAddress(library, "gpr_timespec_to_micros"); - gpr_avl_create_import = (gpr_avl_create_type) GetProcAddress(library, "gpr_avl_create"); - gpr_avl_ref_import = (gpr_avl_ref_type) GetProcAddress(library, "gpr_avl_ref"); - gpr_avl_unref_import = (gpr_avl_unref_type) GetProcAddress(library, "gpr_avl_unref"); - gpr_avl_add_import = (gpr_avl_add_type) GetProcAddress(library, "gpr_avl_add"); - gpr_avl_remove_import = (gpr_avl_remove_type) GetProcAddress(library, "gpr_avl_remove"); - gpr_avl_get_import = (gpr_avl_get_type) GetProcAddress(library, "gpr_avl_get"); - gpr_avl_maybe_get_import = (gpr_avl_maybe_get_type) GetProcAddress(library, "gpr_avl_maybe_get"); - gpr_avl_is_empty_import = (gpr_avl_is_empty_type) GetProcAddress(library, "gpr_avl_is_empty"); - gpr_cmdline_create_import = (gpr_cmdline_create_type) GetProcAddress(library, "gpr_cmdline_create"); - gpr_cmdline_add_int_import = (gpr_cmdline_add_int_type) GetProcAddress(library, "gpr_cmdline_add_int"); - gpr_cmdline_add_flag_import = (gpr_cmdline_add_flag_type) GetProcAddress(library, "gpr_cmdline_add_flag"); - gpr_cmdline_add_string_import = (gpr_cmdline_add_string_type) GetProcAddress(library, "gpr_cmdline_add_string"); - gpr_cmdline_on_extra_arg_import = (gpr_cmdline_on_extra_arg_type) GetProcAddress(library, "gpr_cmdline_on_extra_arg"); - gpr_cmdline_set_survive_failure_import = (gpr_cmdline_set_survive_failure_type) GetProcAddress(library, "gpr_cmdline_set_survive_failure"); - gpr_cmdline_parse_import = (gpr_cmdline_parse_type) GetProcAddress(library, "gpr_cmdline_parse"); - gpr_cmdline_destroy_import = (gpr_cmdline_destroy_type) GetProcAddress(library, "gpr_cmdline_destroy"); - gpr_cmdline_usage_string_import = (gpr_cmdline_usage_string_type) GetProcAddress(library, "gpr_cmdline_usage_string"); - gpr_cpu_num_cores_import = (gpr_cpu_num_cores_type) GetProcAddress(library, "gpr_cpu_num_cores"); - gpr_cpu_current_cpu_import = (gpr_cpu_current_cpu_type) GetProcAddress(library, "gpr_cpu_current_cpu"); - gpr_histogram_create_import = (gpr_histogram_create_type) GetProcAddress(library, "gpr_histogram_create"); - gpr_histogram_destroy_import = (gpr_histogram_destroy_type) GetProcAddress(library, "gpr_histogram_destroy"); - gpr_histogram_add_import = (gpr_histogram_add_type) GetProcAddress(library, "gpr_histogram_add"); - gpr_histogram_merge_import = (gpr_histogram_merge_type) GetProcAddress(library, "gpr_histogram_merge"); - gpr_histogram_percentile_import = (gpr_histogram_percentile_type) GetProcAddress(library, "gpr_histogram_percentile"); - gpr_histogram_mean_import = (gpr_histogram_mean_type) GetProcAddress(library, "gpr_histogram_mean"); - gpr_histogram_stddev_import = (gpr_histogram_stddev_type) GetProcAddress(library, "gpr_histogram_stddev"); - gpr_histogram_variance_import = (gpr_histogram_variance_type) GetProcAddress(library, "gpr_histogram_variance"); - gpr_histogram_maximum_import = (gpr_histogram_maximum_type) GetProcAddress(library, "gpr_histogram_maximum"); - gpr_histogram_minimum_import = (gpr_histogram_minimum_type) GetProcAddress(library, "gpr_histogram_minimum"); - gpr_histogram_count_import = (gpr_histogram_count_type) GetProcAddress(library, "gpr_histogram_count"); - gpr_histogram_sum_import = (gpr_histogram_sum_type) GetProcAddress(library, "gpr_histogram_sum"); - gpr_histogram_sum_of_squares_import = (gpr_histogram_sum_of_squares_type) GetProcAddress(library, "gpr_histogram_sum_of_squares"); - gpr_histogram_get_contents_import = (gpr_histogram_get_contents_type) GetProcAddress(library, "gpr_histogram_get_contents"); - gpr_histogram_merge_contents_import = (gpr_histogram_merge_contents_type) GetProcAddress(library, "gpr_histogram_merge_contents"); - gpr_join_host_port_import = (gpr_join_host_port_type) GetProcAddress(library, "gpr_join_host_port"); - gpr_split_host_port_import = (gpr_split_host_port_type) GetProcAddress(library, "gpr_split_host_port"); - gpr_format_message_import = (gpr_format_message_type) GetProcAddress(library, "gpr_format_message"); - gpr_strdup_import = (gpr_strdup_type) GetProcAddress(library, "gpr_strdup"); - gpr_asprintf_import = (gpr_asprintf_type) GetProcAddress(library, "gpr_asprintf"); - gpr_subprocess_binary_extension_import = (gpr_subprocess_binary_extension_type) GetProcAddress(library, "gpr_subprocess_binary_extension"); - gpr_subprocess_create_import = (gpr_subprocess_create_type) GetProcAddress(library, "gpr_subprocess_create"); - gpr_subprocess_destroy_import = (gpr_subprocess_destroy_type) GetProcAddress(library, "gpr_subprocess_destroy"); - gpr_subprocess_join_import = (gpr_subprocess_join_type) GetProcAddress(library, "gpr_subprocess_join"); - gpr_subprocess_interrupt_import = (gpr_subprocess_interrupt_type) GetProcAddress(library, "gpr_subprocess_interrupt"); - gpr_thd_new_import = (gpr_thd_new_type) GetProcAddress(library, "gpr_thd_new"); - gpr_thd_options_default_import = (gpr_thd_options_default_type) GetProcAddress(library, "gpr_thd_options_default"); - gpr_thd_options_set_detached_import = (gpr_thd_options_set_detached_type) GetProcAddress(library, "gpr_thd_options_set_detached"); - gpr_thd_options_set_joinable_import = (gpr_thd_options_set_joinable_type) GetProcAddress(library, "gpr_thd_options_set_joinable"); - gpr_thd_options_is_detached_import = (gpr_thd_options_is_detached_type) GetProcAddress(library, "gpr_thd_options_is_detached"); - gpr_thd_options_is_joinable_import = (gpr_thd_options_is_joinable_type) GetProcAddress(library, "gpr_thd_options_is_joinable"); - gpr_thd_currentid_import = (gpr_thd_currentid_type) GetProcAddress(library, "gpr_thd_currentid"); - gpr_thd_join_import = (gpr_thd_join_type) GetProcAddress(library, "gpr_thd_join"); -} - -#ifdef __cplusplus -} -#endif /* __cpluslus */ - -#endif /* !GPR_WINDOWS */ diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h deleted file mode 100644 index f87c4da787..0000000000 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ /dev/null @@ -1,900 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef PYGRPC_CYTHON_WINDOWS_IMPORTS_H_ -#define PYGRPC_CYTHON_WINDOWS_IMPORTS_H_ - -#include <grpc/support/port_platform.h> - -#ifdef GPR_WINDOWS - -#include <windows.h> - -#include <grpc/census.h> -#include <grpc/compression.h> -#include <grpc/grpc.h> -#include <grpc/grpc_posix.h> -#include <grpc/grpc_security.h> -#include <grpc/impl/codegen/alloc.h> -#include <grpc/impl/codegen/byte_buffer.h> -#include <grpc/impl/codegen/log.h> -#include <grpc/impl/codegen/slice.h> -#include <grpc/impl/codegen/slice_buffer.h> -#include <grpc/impl/codegen/sync.h> -#include <grpc/impl/codegen/time.h> -#include <grpc/support/avl.h> -#include <grpc/support/cmdline.h> -#include <grpc/support/cpu.h> -#include <grpc/support/histogram.h> -#include <grpc/support/host_port.h> -#include <grpc/support/log_windows.h> -#include <grpc/support/string_util.h> -#include <grpc/support/subprocess.h> -#include <grpc/support/thd.h> - -typedef int(*census_initialize_type)(int features); -extern census_initialize_type census_initialize_import; -#define census_initialize census_initialize_import -typedef void(*census_shutdown_type)(void); -extern census_shutdown_type census_shutdown_import; -#define census_shutdown census_shutdown_import -typedef int(*census_supported_type)(void); -extern census_supported_type census_supported_import; -#define census_supported census_supported_import -typedef int(*census_enabled_type)(void); -extern census_enabled_type census_enabled_import; -#define census_enabled census_enabled_import -typedef census_context *(*census_context_create_type)(const census_context *base, const census_tag *tags, int ntags, census_context_status const **status); -extern census_context_create_type census_context_create_import; -#define census_context_create census_context_create_import -typedef void(*census_context_destroy_type)(census_context *context); -extern census_context_destroy_type census_context_destroy_import; -#define census_context_destroy census_context_destroy_import -typedef const census_context_status *(*census_context_get_status_type)(const census_context *context); -extern census_context_get_status_type census_context_get_status_import; -#define census_context_get_status census_context_get_status_import -typedef void(*census_context_initialize_iterator_type)(const census_context *context, census_context_iterator *iterator); -extern census_context_initialize_iterator_type census_context_initialize_iterator_import; -#define census_context_initialize_iterator census_context_initialize_iterator_import -typedef int(*census_context_next_tag_type)(census_context_iterator *iterator, census_tag *tag); -extern census_context_next_tag_type census_context_next_tag_import; -#define census_context_next_tag census_context_next_tag_import -typedef int(*census_context_get_tag_type)(const census_context *context, const char *key, census_tag *tag); -extern census_context_get_tag_type census_context_get_tag_import; -#define census_context_get_tag census_context_get_tag_import -typedef size_t(*census_context_encode_type)(const census_context *context, char *buffer, size_t buf_size); -extern census_context_encode_type census_context_encode_import; -#define census_context_encode census_context_encode_import -typedef census_context *(*census_context_decode_type)(const char *buffer, size_t size); -extern census_context_decode_type census_context_decode_import; -#define census_context_decode census_context_decode_import -typedef int(*census_trace_mask_type)(const census_context *context); -extern census_trace_mask_type census_trace_mask_import; -#define census_trace_mask census_trace_mask_import -typedef void(*census_set_trace_mask_type)(int trace_mask); -extern census_set_trace_mask_type census_set_trace_mask_import; -#define census_set_trace_mask census_set_trace_mask_import -typedef census_timestamp(*census_start_rpc_op_timestamp_type)(void); -extern census_start_rpc_op_timestamp_type census_start_rpc_op_timestamp_import; -#define census_start_rpc_op_timestamp census_start_rpc_op_timestamp_import -typedef census_context *(*census_start_client_rpc_op_type)(const census_context *context, int64_t rpc_name_id, const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, const census_timestamp *start_time); -extern census_start_client_rpc_op_type census_start_client_rpc_op_import; -#define census_start_client_rpc_op census_start_client_rpc_op_import -typedef void(*census_set_rpc_client_peer_type)(census_context *context, const char *peer); -extern census_set_rpc_client_peer_type census_set_rpc_client_peer_import; -#define census_set_rpc_client_peer census_set_rpc_client_peer_import -typedef census_context *(*census_start_server_rpc_op_type)(const char *buffer, int64_t rpc_name_id, const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, census_timestamp *start_time); -extern census_start_server_rpc_op_type census_start_server_rpc_op_import; -#define census_start_server_rpc_op census_start_server_rpc_op_import -typedef census_context *(*census_start_op_type)(census_context *context, const char *family, const char *name, int trace_mask); -extern census_start_op_type census_start_op_import; -#define census_start_op census_start_op_import -typedef void(*census_end_op_type)(census_context *context, int status); -extern census_end_op_type census_end_op_import; -#define census_end_op census_end_op_import -typedef void(*census_trace_print_type)(census_context *context, uint32_t type, const char *buffer, size_t n); -extern census_trace_print_type census_trace_print_import; -#define census_trace_print census_trace_print_import -typedef int(*census_trace_scan_start_type)(int consume); -extern census_trace_scan_start_type census_trace_scan_start_import; -#define census_trace_scan_start census_trace_scan_start_import -typedef int(*census_get_trace_record_type)(census_trace_record *trace_record); -extern census_get_trace_record_type census_get_trace_record_import; -#define census_get_trace_record census_get_trace_record_import -typedef void(*census_trace_scan_end_type)(); -extern census_trace_scan_end_type census_trace_scan_end_import; -#define census_trace_scan_end census_trace_scan_end_import -typedef void(*census_record_values_type)(census_context *context, census_value *values, size_t nvalues); -extern census_record_values_type census_record_values_import; -#define census_record_values census_record_values_import -typedef census_view *(*census_view_create_type)(uint32_t metric_id, const census_context *tags, const census_aggregation *aggregations, size_t naggregations); -extern census_view_create_type census_view_create_import; -#define census_view_create census_view_create_import -typedef void(*census_view_delete_type)(census_view *view); -extern census_view_delete_type census_view_delete_import; -#define census_view_delete census_view_delete_import -typedef size_t(*census_view_metric_type)(const census_view *view); -extern census_view_metric_type census_view_metric_import; -#define census_view_metric census_view_metric_import -typedef size_t(*census_view_naggregations_type)(const census_view *view); -extern census_view_naggregations_type census_view_naggregations_import; -#define census_view_naggregations census_view_naggregations_import -typedef const census_context *(*census_view_tags_type)(const census_view *view); -extern census_view_tags_type census_view_tags_import; -#define census_view_tags census_view_tags_import -typedef const census_aggregation *(*census_view_aggregrations_type)(const census_view *view); -extern census_view_aggregrations_type census_view_aggregrations_import; -#define census_view_aggregrations census_view_aggregrations_import -typedef const census_view_data *(*census_view_get_data_type)(const census_view *view); -extern census_view_get_data_type census_view_get_data_import; -#define census_view_get_data census_view_get_data_import -typedef void(*census_view_reset_type)(census_view *view); -extern census_view_reset_type census_view_reset_import; -#define census_view_reset census_view_reset_import -typedef int(*grpc_compression_algorithm_parse_type)(const char *name, size_t name_length, grpc_compression_algorithm *algorithm); -extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import; -#define grpc_compression_algorithm_parse grpc_compression_algorithm_parse_import -typedef int(*grpc_compression_algorithm_name_type)(grpc_compression_algorithm algorithm, char **name); -extern grpc_compression_algorithm_name_type grpc_compression_algorithm_name_import; -#define grpc_compression_algorithm_name grpc_compression_algorithm_name_import -typedef grpc_compression_algorithm(*grpc_compression_algorithm_for_level_type)(grpc_compression_level level, uint32_t accepted_encodings); -extern grpc_compression_algorithm_for_level_type grpc_compression_algorithm_for_level_import; -#define grpc_compression_algorithm_for_level grpc_compression_algorithm_for_level_import -typedef void(*grpc_compression_options_init_type)(grpc_compression_options *opts); -extern grpc_compression_options_init_type grpc_compression_options_init_import; -#define grpc_compression_options_init grpc_compression_options_init_import -typedef void(*grpc_compression_options_enable_algorithm_type)(grpc_compression_options *opts, grpc_compression_algorithm algorithm); -extern grpc_compression_options_enable_algorithm_type grpc_compression_options_enable_algorithm_import; -#define grpc_compression_options_enable_algorithm grpc_compression_options_enable_algorithm_import -typedef void(*grpc_compression_options_disable_algorithm_type)(grpc_compression_options *opts, grpc_compression_algorithm algorithm); -extern grpc_compression_options_disable_algorithm_type grpc_compression_options_disable_algorithm_import; -#define grpc_compression_options_disable_algorithm grpc_compression_options_disable_algorithm_import -typedef int(*grpc_compression_options_is_algorithm_enabled_type)(const grpc_compression_options *opts, grpc_compression_algorithm algorithm); -extern grpc_compression_options_is_algorithm_enabled_type grpc_compression_options_is_algorithm_enabled_import; -#define grpc_compression_options_is_algorithm_enabled grpc_compression_options_is_algorithm_enabled_import -typedef void(*grpc_metadata_array_init_type)(grpc_metadata_array *array); -extern grpc_metadata_array_init_type grpc_metadata_array_init_import; -#define grpc_metadata_array_init grpc_metadata_array_init_import -typedef void(*grpc_metadata_array_destroy_type)(grpc_metadata_array *array); -extern grpc_metadata_array_destroy_type grpc_metadata_array_destroy_import; -#define grpc_metadata_array_destroy grpc_metadata_array_destroy_import -typedef void(*grpc_call_details_init_type)(grpc_call_details *details); -extern grpc_call_details_init_type grpc_call_details_init_import; -#define grpc_call_details_init grpc_call_details_init_import -typedef void(*grpc_call_details_destroy_type)(grpc_call_details *details); -extern grpc_call_details_destroy_type grpc_call_details_destroy_import; -#define grpc_call_details_destroy grpc_call_details_destroy_import -typedef void(*grpc_register_plugin_type)(void (*init)(void), void (*destroy)(void)); -extern grpc_register_plugin_type grpc_register_plugin_import; -#define grpc_register_plugin grpc_register_plugin_import -typedef void(*grpc_init_type)(void); -extern grpc_init_type grpc_init_import; -#define grpc_init grpc_init_import -typedef void(*grpc_shutdown_type)(void); -extern grpc_shutdown_type grpc_shutdown_import; -#define grpc_shutdown grpc_shutdown_import -typedef const char *(*grpc_version_string_type)(void); -extern grpc_version_string_type grpc_version_string_import; -#define grpc_version_string grpc_version_string_import -typedef grpc_completion_queue *(*grpc_completion_queue_create_type)(void *reserved); -extern grpc_completion_queue_create_type grpc_completion_queue_create_import; -#define grpc_completion_queue_create grpc_completion_queue_create_import -typedef grpc_event(*grpc_completion_queue_next_type)(grpc_completion_queue *cq, gpr_timespec deadline, void *reserved); -extern grpc_completion_queue_next_type grpc_completion_queue_next_import; -#define grpc_completion_queue_next grpc_completion_queue_next_import -typedef grpc_event(*grpc_completion_queue_pluck_type)(grpc_completion_queue *cq, void *tag, gpr_timespec deadline, void *reserved); -extern grpc_completion_queue_pluck_type grpc_completion_queue_pluck_import; -#define grpc_completion_queue_pluck grpc_completion_queue_pluck_import -typedef void(*grpc_completion_queue_shutdown_type)(grpc_completion_queue *cq); -extern grpc_completion_queue_shutdown_type grpc_completion_queue_shutdown_import; -#define grpc_completion_queue_shutdown grpc_completion_queue_shutdown_import -typedef void(*grpc_completion_queue_destroy_type)(grpc_completion_queue *cq); -extern grpc_completion_queue_destroy_type grpc_completion_queue_destroy_import; -#define grpc_completion_queue_destroy grpc_completion_queue_destroy_import -typedef grpc_alarm *(*grpc_alarm_create_type)(grpc_completion_queue *cq, gpr_timespec deadline, void *tag); -extern grpc_alarm_create_type grpc_alarm_create_import; -#define grpc_alarm_create grpc_alarm_create_import -typedef void(*grpc_alarm_cancel_type)(grpc_alarm *alarm); -extern grpc_alarm_cancel_type grpc_alarm_cancel_import; -#define grpc_alarm_cancel grpc_alarm_cancel_import -typedef void(*grpc_alarm_destroy_type)(grpc_alarm *alarm); -extern grpc_alarm_destroy_type grpc_alarm_destroy_import; -#define grpc_alarm_destroy grpc_alarm_destroy_import -typedef grpc_connectivity_state(*grpc_channel_check_connectivity_state_type)(grpc_channel *channel, int try_to_connect); -extern grpc_channel_check_connectivity_state_type grpc_channel_check_connectivity_state_import; -#define grpc_channel_check_connectivity_state grpc_channel_check_connectivity_state_import -typedef void(*grpc_channel_watch_connectivity_state_type)(grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag); -extern grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import; -#define grpc_channel_watch_connectivity_state grpc_channel_watch_connectivity_state_import -typedef grpc_call *(*grpc_channel_create_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, const char *method, const char *host, gpr_timespec deadline, void *reserved); -extern grpc_channel_create_call_type grpc_channel_create_call_import; -#define grpc_channel_create_call grpc_channel_create_call_import -typedef void(*grpc_channel_ping_type)(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved); -extern grpc_channel_ping_type grpc_channel_ping_import; -#define grpc_channel_ping grpc_channel_ping_import -typedef void *(*grpc_channel_register_call_type)(grpc_channel *channel, const char *method, const char *host, void *reserved); -extern grpc_channel_register_call_type grpc_channel_register_call_import; -#define grpc_channel_register_call grpc_channel_register_call_import -typedef grpc_call *(*grpc_channel_create_registered_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline, void *reserved); -extern grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import; -#define grpc_channel_create_registered_call grpc_channel_create_registered_call_import -typedef grpc_call_error(*grpc_call_start_batch_type)(grpc_call *call, const grpc_op *ops, size_t nops, void *tag, void *reserved); -extern grpc_call_start_batch_type grpc_call_start_batch_import; -#define grpc_call_start_batch grpc_call_start_batch_import -typedef char *(*grpc_call_get_peer_type)(grpc_call *call); -extern grpc_call_get_peer_type grpc_call_get_peer_import; -#define grpc_call_get_peer grpc_call_get_peer_import -typedef void(*grpc_census_call_set_context_type)(grpc_call *call, struct census_context *context); -extern grpc_census_call_set_context_type grpc_census_call_set_context_import; -#define grpc_census_call_set_context grpc_census_call_set_context_import -typedef struct census_context *(*grpc_census_call_get_context_type)(grpc_call *call); -extern grpc_census_call_get_context_type grpc_census_call_get_context_import; -#define grpc_census_call_get_context grpc_census_call_get_context_import -typedef char *(*grpc_channel_get_target_type)(grpc_channel *channel); -extern grpc_channel_get_target_type grpc_channel_get_target_import; -#define grpc_channel_get_target grpc_channel_get_target_import -typedef grpc_channel *(*grpc_insecure_channel_create_type)(const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_insecure_channel_create_type grpc_insecure_channel_create_import; -#define grpc_insecure_channel_create grpc_insecure_channel_create_import -typedef grpc_channel *(*grpc_lame_client_channel_create_type)(const char *target, grpc_status_code error_code, const char *error_message); -extern grpc_lame_client_channel_create_type grpc_lame_client_channel_create_import; -#define grpc_lame_client_channel_create grpc_lame_client_channel_create_import -typedef void(*grpc_channel_destroy_type)(grpc_channel *channel); -extern grpc_channel_destroy_type grpc_channel_destroy_import; -#define grpc_channel_destroy grpc_channel_destroy_import -typedef grpc_call_error(*grpc_call_cancel_type)(grpc_call *call, void *reserved); -extern grpc_call_cancel_type grpc_call_cancel_import; -#define grpc_call_cancel grpc_call_cancel_import -typedef grpc_call_error(*grpc_call_cancel_with_status_type)(grpc_call *call, grpc_status_code status, const char *description, void *reserved); -extern grpc_call_cancel_with_status_type grpc_call_cancel_with_status_import; -#define grpc_call_cancel_with_status grpc_call_cancel_with_status_import -typedef void(*grpc_call_destroy_type)(grpc_call *call); -extern grpc_call_destroy_type grpc_call_destroy_import; -#define grpc_call_destroy grpc_call_destroy_import -typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); -extern grpc_server_request_call_type grpc_server_request_call_import; -#define grpc_server_request_call grpc_server_request_call_import -typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags); -extern grpc_server_register_method_type grpc_server_register_method_import; -#define grpc_server_register_method grpc_server_register_method_import -typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); -extern grpc_server_request_registered_call_type grpc_server_request_registered_call_import; -#define grpc_server_request_registered_call grpc_server_request_registered_call_import -typedef grpc_server *(*grpc_server_create_type)(const grpc_channel_args *args, void *reserved); -extern grpc_server_create_type grpc_server_create_import; -#define grpc_server_create grpc_server_create_import -typedef void(*grpc_server_register_completion_queue_type)(grpc_server *server, grpc_completion_queue *cq, void *reserved); -extern grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import; -#define grpc_server_register_completion_queue grpc_server_register_completion_queue_import -typedef void(*grpc_server_register_non_listening_completion_queue_type)(grpc_server *server, grpc_completion_queue *q, void *reserved); -extern grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import; -#define grpc_server_register_non_listening_completion_queue grpc_server_register_non_listening_completion_queue_import -typedef int(*grpc_server_add_insecure_http2_port_type)(grpc_server *server, const char *addr); -extern grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import; -#define grpc_server_add_insecure_http2_port grpc_server_add_insecure_http2_port_import -typedef void(*grpc_server_start_type)(grpc_server *server); -extern grpc_server_start_type grpc_server_start_import; -#define grpc_server_start grpc_server_start_import -typedef void(*grpc_server_shutdown_and_notify_type)(grpc_server *server, grpc_completion_queue *cq, void *tag); -extern grpc_server_shutdown_and_notify_type grpc_server_shutdown_and_notify_import; -#define grpc_server_shutdown_and_notify grpc_server_shutdown_and_notify_import -typedef void(*grpc_server_cancel_all_calls_type)(grpc_server *server); -extern grpc_server_cancel_all_calls_type grpc_server_cancel_all_calls_import; -#define grpc_server_cancel_all_calls grpc_server_cancel_all_calls_import -typedef void(*grpc_server_destroy_type)(grpc_server *server); -extern grpc_server_destroy_type grpc_server_destroy_import; -#define grpc_server_destroy grpc_server_destroy_import -typedef int(*grpc_tracer_set_enabled_type)(const char *name, int enabled); -extern grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import; -#define grpc_tracer_set_enabled grpc_tracer_set_enabled_import -typedef int(*grpc_header_key_is_legal_type)(const char *key, size_t length); -extern grpc_header_key_is_legal_type grpc_header_key_is_legal_import; -#define grpc_header_key_is_legal grpc_header_key_is_legal_import -typedef int(*grpc_header_nonbin_value_is_legal_type)(const char *value, size_t length); -extern grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; -#define grpc_header_nonbin_value_is_legal grpc_header_nonbin_value_is_legal_import -typedef int(*grpc_is_binary_header_type)(const char *key, size_t length); -extern grpc_is_binary_header_type grpc_is_binary_header_import; -#define grpc_is_binary_header grpc_is_binary_header_import -typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); -extern grpc_call_error_to_string_type grpc_call_error_to_string_import; -#define grpc_call_error_to_string grpc_call_error_to_string_import -typedef grpc_channel *(*grpc_insecure_channel_create_from_fd_type)(const char *target, int fd, const grpc_channel_args *args); -extern grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; -#define grpc_insecure_channel_create_from_fd grpc_insecure_channel_create_from_fd_import -typedef void(*grpc_server_add_insecure_channel_from_fd_type)(grpc_server *server, grpc_completion_queue *cq, int fd); -extern grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import; -#define grpc_server_add_insecure_channel_from_fd grpc_server_add_insecure_channel_from_fd_import -typedef void(*grpc_use_signal_type)(int signum); -extern grpc_use_signal_type grpc_use_signal_import; -#define grpc_use_signal grpc_use_signal_import -typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); -extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; -#define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import -typedef grpc_auth_property_iterator(*grpc_auth_context_property_iterator_type)(const grpc_auth_context *ctx); -extern grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; -#define grpc_auth_context_property_iterator grpc_auth_context_property_iterator_import -typedef grpc_auth_property_iterator(*grpc_auth_context_peer_identity_type)(const grpc_auth_context *ctx); -extern grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; -#define grpc_auth_context_peer_identity grpc_auth_context_peer_identity_import -typedef grpc_auth_property_iterator(*grpc_auth_context_find_properties_by_name_type)(const grpc_auth_context *ctx, const char *name); -extern grpc_auth_context_find_properties_by_name_type grpc_auth_context_find_properties_by_name_import; -#define grpc_auth_context_find_properties_by_name grpc_auth_context_find_properties_by_name_import -typedef const char *(*grpc_auth_context_peer_identity_property_name_type)(const grpc_auth_context *ctx); -extern grpc_auth_context_peer_identity_property_name_type grpc_auth_context_peer_identity_property_name_import; -#define grpc_auth_context_peer_identity_property_name grpc_auth_context_peer_identity_property_name_import -typedef int(*grpc_auth_context_peer_is_authenticated_type)(const grpc_auth_context *ctx); -extern grpc_auth_context_peer_is_authenticated_type grpc_auth_context_peer_is_authenticated_import; -#define grpc_auth_context_peer_is_authenticated grpc_auth_context_peer_is_authenticated_import -typedef grpc_auth_context *(*grpc_call_auth_context_type)(grpc_call *call); -extern grpc_call_auth_context_type grpc_call_auth_context_import; -#define grpc_call_auth_context grpc_call_auth_context_import -typedef void(*grpc_auth_context_release_type)(grpc_auth_context *context); -extern grpc_auth_context_release_type grpc_auth_context_release_import; -#define grpc_auth_context_release grpc_auth_context_release_import -typedef void(*grpc_auth_context_add_property_type)(grpc_auth_context *ctx, const char *name, const char *value, size_t value_length); -extern grpc_auth_context_add_property_type grpc_auth_context_add_property_import; -#define grpc_auth_context_add_property grpc_auth_context_add_property_import -typedef void(*grpc_auth_context_add_cstring_property_type)(grpc_auth_context *ctx, const char *name, const char *value); -extern grpc_auth_context_add_cstring_property_type grpc_auth_context_add_cstring_property_import; -#define grpc_auth_context_add_cstring_property grpc_auth_context_add_cstring_property_import -typedef int(*grpc_auth_context_set_peer_identity_property_name_type)(grpc_auth_context *ctx, const char *name); -extern grpc_auth_context_set_peer_identity_property_name_type grpc_auth_context_set_peer_identity_property_name_import; -#define grpc_auth_context_set_peer_identity_property_name grpc_auth_context_set_peer_identity_property_name_import -typedef void(*grpc_channel_credentials_release_type)(grpc_channel_credentials *creds); -extern grpc_channel_credentials_release_type grpc_channel_credentials_release_import; -#define grpc_channel_credentials_release grpc_channel_credentials_release_import -typedef grpc_channel_credentials *(*grpc_google_default_credentials_create_type)(void); -extern grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import; -#define grpc_google_default_credentials_create grpc_google_default_credentials_create_import -typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb); -extern grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import; -#define grpc_set_ssl_roots_override_callback grpc_set_ssl_roots_override_callback_import -typedef grpc_channel_credentials *(*grpc_ssl_credentials_create_type)(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, void *reserved); -extern grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import; -#define grpc_ssl_credentials_create grpc_ssl_credentials_create_import -typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials *creds); -extern grpc_call_credentials_release_type grpc_call_credentials_release_import; -#define grpc_call_credentials_release grpc_call_credentials_release_import -typedef grpc_channel_credentials *(*grpc_composite_channel_credentials_create_type)(grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds, void *reserved); -extern grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import; -#define grpc_composite_channel_credentials_create grpc_composite_channel_credentials_create_import -typedef grpc_call_credentials *(*grpc_composite_call_credentials_create_type)(grpc_call_credentials *creds1, grpc_call_credentials *creds2, void *reserved); -extern grpc_composite_call_credentials_create_type grpc_composite_call_credentials_create_import; -#define grpc_composite_call_credentials_create grpc_composite_call_credentials_create_import -typedef grpc_call_credentials *(*grpc_google_compute_engine_credentials_create_type)(void *reserved); -extern grpc_google_compute_engine_credentials_create_type grpc_google_compute_engine_credentials_create_import; -#define grpc_google_compute_engine_credentials_create grpc_google_compute_engine_credentials_create_import -typedef gpr_timespec(*grpc_max_auth_token_lifetime_type)(); -extern grpc_max_auth_token_lifetime_type grpc_max_auth_token_lifetime_import; -#define grpc_max_auth_token_lifetime grpc_max_auth_token_lifetime_import -typedef grpc_call_credentials *(*grpc_service_account_jwt_access_credentials_create_type)(const char *json_key, gpr_timespec token_lifetime, void *reserved); -extern grpc_service_account_jwt_access_credentials_create_type grpc_service_account_jwt_access_credentials_create_import; -#define grpc_service_account_jwt_access_credentials_create grpc_service_account_jwt_access_credentials_create_import -typedef grpc_call_credentials *(*grpc_google_refresh_token_credentials_create_type)(const char *json_refresh_token, void *reserved); -extern grpc_google_refresh_token_credentials_create_type grpc_google_refresh_token_credentials_create_import; -#define grpc_google_refresh_token_credentials_create grpc_google_refresh_token_credentials_create_import -typedef grpc_call_credentials *(*grpc_access_token_credentials_create_type)(const char *access_token, void *reserved); -extern grpc_access_token_credentials_create_type grpc_access_token_credentials_create_import; -#define grpc_access_token_credentials_create grpc_access_token_credentials_create_import -typedef grpc_call_credentials *(*grpc_google_iam_credentials_create_type)(const char *authorization_token, const char *authority_selector, void *reserved); -extern grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_import; -#define grpc_google_iam_credentials_create grpc_google_iam_credentials_create_import -typedef grpc_call_credentials *(*grpc_metadata_credentials_create_from_plugin_type)(grpc_metadata_credentials_plugin plugin, void *reserved); -extern grpc_metadata_credentials_create_from_plugin_type grpc_metadata_credentials_create_from_plugin_import; -#define grpc_metadata_credentials_create_from_plugin grpc_metadata_credentials_create_from_plugin_import -typedef grpc_channel *(*grpc_secure_channel_create_type)(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_secure_channel_create_type grpc_secure_channel_create_import; -#define grpc_secure_channel_create grpc_secure_channel_create_import -typedef void(*grpc_server_credentials_release_type)(grpc_server_credentials *creds); -extern grpc_server_credentials_release_type grpc_server_credentials_release_import; -#define grpc_server_credentials_release grpc_server_credentials_release_import -typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_type)(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved); -extern grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import; -#define grpc_ssl_server_credentials_create grpc_ssl_server_credentials_create_import -typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_ex_type)(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, grpc_ssl_client_certificate_request_type client_certificate_request, void *reserved); -extern grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import; -#define grpc_ssl_server_credentials_create_ex grpc_ssl_server_credentials_create_ex_import -typedef int(*grpc_server_add_secure_http2_port_type)(grpc_server *server, const char *addr, grpc_server_credentials *creds); -extern grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import; -#define grpc_server_add_secure_http2_port grpc_server_add_secure_http2_port_import -typedef grpc_call_error(*grpc_call_set_credentials_type)(grpc_call *call, grpc_call_credentials *creds); -extern grpc_call_set_credentials_type grpc_call_set_credentials_import; -#define grpc_call_set_credentials grpc_call_set_credentials_import -typedef void(*grpc_server_credentials_set_auth_metadata_processor_type)(grpc_server_credentials *creds, grpc_auth_metadata_processor processor); -extern grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import; -#define grpc_server_credentials_set_auth_metadata_processor grpc_server_credentials_set_auth_metadata_processor_import -typedef void *(*gpr_malloc_type)(size_t size); -extern gpr_malloc_type gpr_malloc_import; -#define gpr_malloc gpr_malloc_import -typedef void(*gpr_free_type)(void *ptr); -extern gpr_free_type gpr_free_import; -#define gpr_free gpr_free_import -typedef void *(*gpr_realloc_type)(void *p, size_t size); -extern gpr_realloc_type gpr_realloc_import; -#define gpr_realloc gpr_realloc_import -typedef void *(*gpr_malloc_aligned_type)(size_t size, size_t alignment_log); -extern gpr_malloc_aligned_type gpr_malloc_aligned_import; -#define gpr_malloc_aligned gpr_malloc_aligned_import -typedef void(*gpr_free_aligned_type)(void *ptr); -extern gpr_free_aligned_type gpr_free_aligned_import; -#define gpr_free_aligned gpr_free_aligned_import -typedef void(*gpr_set_allocation_functions_type)(gpr_allocation_functions functions); -extern gpr_set_allocation_functions_type gpr_set_allocation_functions_import; -#define gpr_set_allocation_functions gpr_set_allocation_functions_import -typedef gpr_allocation_functions(*gpr_get_allocation_functions_type)(); -extern gpr_get_allocation_functions_type gpr_get_allocation_functions_import; -#define gpr_get_allocation_functions gpr_get_allocation_functions_import -typedef grpc_byte_buffer *(*grpc_raw_byte_buffer_create_type)(gpr_slice *slices, size_t nslices); -extern grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; -#define grpc_raw_byte_buffer_create grpc_raw_byte_buffer_create_import -typedef grpc_byte_buffer *(*grpc_raw_compressed_byte_buffer_create_type)(gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression); -extern grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; -#define grpc_raw_compressed_byte_buffer_create grpc_raw_compressed_byte_buffer_create_import -typedef grpc_byte_buffer *(*grpc_byte_buffer_copy_type)(grpc_byte_buffer *bb); -extern grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import; -#define grpc_byte_buffer_copy grpc_byte_buffer_copy_import -typedef size_t(*grpc_byte_buffer_length_type)(grpc_byte_buffer *bb); -extern grpc_byte_buffer_length_type grpc_byte_buffer_length_import; -#define grpc_byte_buffer_length grpc_byte_buffer_length_import -typedef void(*grpc_byte_buffer_destroy_type)(grpc_byte_buffer *byte_buffer); -extern grpc_byte_buffer_destroy_type grpc_byte_buffer_destroy_import; -#define grpc_byte_buffer_destroy grpc_byte_buffer_destroy_import -typedef int(*grpc_byte_buffer_reader_init_type)(grpc_byte_buffer_reader *reader, grpc_byte_buffer *buffer); -extern grpc_byte_buffer_reader_init_type grpc_byte_buffer_reader_init_import; -#define grpc_byte_buffer_reader_init grpc_byte_buffer_reader_init_import -typedef void(*grpc_byte_buffer_reader_destroy_type)(grpc_byte_buffer_reader *reader); -extern grpc_byte_buffer_reader_destroy_type grpc_byte_buffer_reader_destroy_import; -#define grpc_byte_buffer_reader_destroy grpc_byte_buffer_reader_destroy_import -typedef int(*grpc_byte_buffer_reader_next_type)(grpc_byte_buffer_reader *reader, gpr_slice *slice); -extern grpc_byte_buffer_reader_next_type grpc_byte_buffer_reader_next_import; -#define grpc_byte_buffer_reader_next grpc_byte_buffer_reader_next_import -typedef gpr_slice(*grpc_byte_buffer_reader_readall_type)(grpc_byte_buffer_reader *reader); -extern grpc_byte_buffer_reader_readall_type grpc_byte_buffer_reader_readall_import; -#define grpc_byte_buffer_reader_readall grpc_byte_buffer_reader_readall_import -typedef grpc_byte_buffer *(*grpc_raw_byte_buffer_from_reader_type)(grpc_byte_buffer_reader *reader); -extern grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import; -#define grpc_raw_byte_buffer_from_reader grpc_raw_byte_buffer_from_reader_import -typedef void(*gpr_log_type)(const char *file, int line, gpr_log_severity severity, const char *format, ...) GPRC_PRINT_FORMAT_CHECK(4, 5); -extern gpr_log_type gpr_log_import; -#define gpr_log gpr_log_import -typedef void(*gpr_log_message_type)(const char *file, int line, gpr_log_severity severity, const char *message); -extern gpr_log_message_type gpr_log_message_import; -#define gpr_log_message gpr_log_message_import -typedef void(*gpr_set_log_verbosity_type)(gpr_log_severity min_severity_to_print); -extern gpr_set_log_verbosity_type gpr_set_log_verbosity_import; -#define gpr_set_log_verbosity gpr_set_log_verbosity_import -typedef void(*gpr_log_verbosity_init_type)(); -extern gpr_log_verbosity_init_type gpr_log_verbosity_init_import; -#define gpr_log_verbosity_init gpr_log_verbosity_init_import -typedef void(*gpr_set_log_function_type)(gpr_log_func func); -extern gpr_set_log_function_type gpr_set_log_function_import; -#define gpr_set_log_function gpr_set_log_function_import -typedef gpr_slice(*gpr_slice_ref_type)(gpr_slice s); -extern gpr_slice_ref_type gpr_slice_ref_import; -#define gpr_slice_ref gpr_slice_ref_import -typedef void(*gpr_slice_unref_type)(gpr_slice s); -extern gpr_slice_unref_type gpr_slice_unref_import; -#define gpr_slice_unref gpr_slice_unref_import -typedef gpr_slice(*gpr_slice_new_type)(void *p, size_t len, void (*destroy)(void *)); -extern gpr_slice_new_type gpr_slice_new_import; -#define gpr_slice_new gpr_slice_new_import -typedef gpr_slice(*gpr_slice_new_with_len_type)(void *p, size_t len, void (*destroy)(void *, size_t)); -extern gpr_slice_new_with_len_type gpr_slice_new_with_len_import; -#define gpr_slice_new_with_len gpr_slice_new_with_len_import -typedef gpr_slice(*gpr_slice_malloc_type)(size_t length); -extern gpr_slice_malloc_type gpr_slice_malloc_import; -#define gpr_slice_malloc gpr_slice_malloc_import -typedef gpr_slice(*gpr_slice_from_copied_string_type)(const char *source); -extern gpr_slice_from_copied_string_type gpr_slice_from_copied_string_import; -#define gpr_slice_from_copied_string gpr_slice_from_copied_string_import -typedef gpr_slice(*gpr_slice_from_copied_buffer_type)(const char *source, size_t len); -extern gpr_slice_from_copied_buffer_type gpr_slice_from_copied_buffer_import; -#define gpr_slice_from_copied_buffer gpr_slice_from_copied_buffer_import -typedef gpr_slice(*gpr_slice_from_static_string_type)(const char *source); -extern gpr_slice_from_static_string_type gpr_slice_from_static_string_import; -#define gpr_slice_from_static_string gpr_slice_from_static_string_import -typedef gpr_slice(*gpr_slice_sub_type)(gpr_slice s, size_t begin, size_t end); -extern gpr_slice_sub_type gpr_slice_sub_import; -#define gpr_slice_sub gpr_slice_sub_import -typedef gpr_slice(*gpr_slice_sub_no_ref_type)(gpr_slice s, size_t begin, size_t end); -extern gpr_slice_sub_no_ref_type gpr_slice_sub_no_ref_import; -#define gpr_slice_sub_no_ref gpr_slice_sub_no_ref_import -typedef gpr_slice(*gpr_slice_split_tail_type)(gpr_slice *s, size_t split); -extern gpr_slice_split_tail_type gpr_slice_split_tail_import; -#define gpr_slice_split_tail gpr_slice_split_tail_import -typedef gpr_slice(*gpr_slice_split_head_type)(gpr_slice *s, size_t split); -extern gpr_slice_split_head_type gpr_slice_split_head_import; -#define gpr_slice_split_head gpr_slice_split_head_import -typedef gpr_slice(*gpr_empty_slice_type)(void); -extern gpr_empty_slice_type gpr_empty_slice_import; -#define gpr_empty_slice gpr_empty_slice_import -typedef int(*gpr_slice_cmp_type)(gpr_slice a, gpr_slice b); -extern gpr_slice_cmp_type gpr_slice_cmp_import; -#define gpr_slice_cmp gpr_slice_cmp_import -typedef int(*gpr_slice_str_cmp_type)(gpr_slice a, const char *b); -extern gpr_slice_str_cmp_type gpr_slice_str_cmp_import; -#define gpr_slice_str_cmp gpr_slice_str_cmp_import -typedef void(*gpr_slice_buffer_init_type)(gpr_slice_buffer *sb); -extern gpr_slice_buffer_init_type gpr_slice_buffer_init_import; -#define gpr_slice_buffer_init gpr_slice_buffer_init_import -typedef void(*gpr_slice_buffer_destroy_type)(gpr_slice_buffer *sb); -extern gpr_slice_buffer_destroy_type gpr_slice_buffer_destroy_import; -#define gpr_slice_buffer_destroy gpr_slice_buffer_destroy_import -typedef void(*gpr_slice_buffer_add_type)(gpr_slice_buffer *sb, gpr_slice slice); -extern gpr_slice_buffer_add_type gpr_slice_buffer_add_import; -#define gpr_slice_buffer_add gpr_slice_buffer_add_import -typedef size_t(*gpr_slice_buffer_add_indexed_type)(gpr_slice_buffer *sb, gpr_slice slice); -extern gpr_slice_buffer_add_indexed_type gpr_slice_buffer_add_indexed_import; -#define gpr_slice_buffer_add_indexed gpr_slice_buffer_add_indexed_import -typedef void(*gpr_slice_buffer_addn_type)(gpr_slice_buffer *sb, gpr_slice *slices, size_t n); -extern gpr_slice_buffer_addn_type gpr_slice_buffer_addn_import; -#define gpr_slice_buffer_addn gpr_slice_buffer_addn_import -typedef uint8_t *(*gpr_slice_buffer_tiny_add_type)(gpr_slice_buffer *sb, size_t len); -extern gpr_slice_buffer_tiny_add_type gpr_slice_buffer_tiny_add_import; -#define gpr_slice_buffer_tiny_add gpr_slice_buffer_tiny_add_import -typedef void(*gpr_slice_buffer_pop_type)(gpr_slice_buffer *sb); -extern gpr_slice_buffer_pop_type gpr_slice_buffer_pop_import; -#define gpr_slice_buffer_pop gpr_slice_buffer_pop_import -typedef void(*gpr_slice_buffer_reset_and_unref_type)(gpr_slice_buffer *sb); -extern gpr_slice_buffer_reset_and_unref_type gpr_slice_buffer_reset_and_unref_import; -#define gpr_slice_buffer_reset_and_unref gpr_slice_buffer_reset_and_unref_import -typedef void(*gpr_slice_buffer_swap_type)(gpr_slice_buffer *a, gpr_slice_buffer *b); -extern gpr_slice_buffer_swap_type gpr_slice_buffer_swap_import; -#define gpr_slice_buffer_swap gpr_slice_buffer_swap_import -typedef void(*gpr_slice_buffer_move_into_type)(gpr_slice_buffer *src, gpr_slice_buffer *dst); -extern gpr_slice_buffer_move_into_type gpr_slice_buffer_move_into_import; -#define gpr_slice_buffer_move_into gpr_slice_buffer_move_into_import -typedef void(*gpr_slice_buffer_trim_end_type)(gpr_slice_buffer *src, size_t n, gpr_slice_buffer *garbage); -extern gpr_slice_buffer_trim_end_type gpr_slice_buffer_trim_end_import; -#define gpr_slice_buffer_trim_end gpr_slice_buffer_trim_end_import -typedef void(*gpr_slice_buffer_move_first_type)(gpr_slice_buffer *src, size_t n, gpr_slice_buffer *dst); -extern gpr_slice_buffer_move_first_type gpr_slice_buffer_move_first_import; -#define gpr_slice_buffer_move_first gpr_slice_buffer_move_first_import -typedef gpr_slice(*gpr_slice_buffer_take_first_type)(gpr_slice_buffer *src); -extern gpr_slice_buffer_take_first_type gpr_slice_buffer_take_first_import; -#define gpr_slice_buffer_take_first gpr_slice_buffer_take_first_import -typedef void(*gpr_mu_init_type)(gpr_mu *mu); -extern gpr_mu_init_type gpr_mu_init_import; -#define gpr_mu_init gpr_mu_init_import -typedef void(*gpr_mu_destroy_type)(gpr_mu *mu); -extern gpr_mu_destroy_type gpr_mu_destroy_import; -#define gpr_mu_destroy gpr_mu_destroy_import -typedef void(*gpr_mu_lock_type)(gpr_mu *mu); -extern gpr_mu_lock_type gpr_mu_lock_import; -#define gpr_mu_lock gpr_mu_lock_import -typedef void(*gpr_mu_unlock_type)(gpr_mu *mu); -extern gpr_mu_unlock_type gpr_mu_unlock_import; -#define gpr_mu_unlock gpr_mu_unlock_import -typedef int(*gpr_mu_trylock_type)(gpr_mu *mu); -extern gpr_mu_trylock_type gpr_mu_trylock_import; -#define gpr_mu_trylock gpr_mu_trylock_import -typedef void(*gpr_cv_init_type)(gpr_cv *cv); -extern gpr_cv_init_type gpr_cv_init_import; -#define gpr_cv_init gpr_cv_init_import -typedef void(*gpr_cv_destroy_type)(gpr_cv *cv); -extern gpr_cv_destroy_type gpr_cv_destroy_import; -#define gpr_cv_destroy gpr_cv_destroy_import -typedef int(*gpr_cv_wait_type)(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline); -extern gpr_cv_wait_type gpr_cv_wait_import; -#define gpr_cv_wait gpr_cv_wait_import -typedef void(*gpr_cv_signal_type)(gpr_cv *cv); -extern gpr_cv_signal_type gpr_cv_signal_import; -#define gpr_cv_signal gpr_cv_signal_import -typedef void(*gpr_cv_broadcast_type)(gpr_cv *cv); -extern gpr_cv_broadcast_type gpr_cv_broadcast_import; -#define gpr_cv_broadcast gpr_cv_broadcast_import -typedef void(*gpr_once_init_type)(gpr_once *once, void (*init_routine)(void)); -extern gpr_once_init_type gpr_once_init_import; -#define gpr_once_init gpr_once_init_import -typedef void(*gpr_event_init_type)(gpr_event *ev); -extern gpr_event_init_type gpr_event_init_import; -#define gpr_event_init gpr_event_init_import -typedef void(*gpr_event_set_type)(gpr_event *ev, void *value); -extern gpr_event_set_type gpr_event_set_import; -#define gpr_event_set gpr_event_set_import -typedef void *(*gpr_event_get_type)(gpr_event *ev); -extern gpr_event_get_type gpr_event_get_import; -#define gpr_event_get gpr_event_get_import -typedef void *(*gpr_event_wait_type)(gpr_event *ev, gpr_timespec abs_deadline); -extern gpr_event_wait_type gpr_event_wait_import; -#define gpr_event_wait gpr_event_wait_import -typedef void(*gpr_ref_init_type)(gpr_refcount *r, int n); -extern gpr_ref_init_type gpr_ref_init_import; -#define gpr_ref_init gpr_ref_init_import -typedef void(*gpr_ref_type)(gpr_refcount *r); -extern gpr_ref_type gpr_ref_import; -#define gpr_ref gpr_ref_import -typedef void(*gpr_ref_non_zero_type)(gpr_refcount *r); -extern gpr_ref_non_zero_type gpr_ref_non_zero_import; -#define gpr_ref_non_zero gpr_ref_non_zero_import -typedef void(*gpr_refn_type)(gpr_refcount *r, int n); -extern gpr_refn_type gpr_refn_import; -#define gpr_refn gpr_refn_import -typedef int(*gpr_unref_type)(gpr_refcount *r); -extern gpr_unref_type gpr_unref_import; -#define gpr_unref gpr_unref_import -typedef void(*gpr_stats_init_type)(gpr_stats_counter *c, intptr_t n); -extern gpr_stats_init_type gpr_stats_init_import; -#define gpr_stats_init gpr_stats_init_import -typedef void(*gpr_stats_inc_type)(gpr_stats_counter *c, intptr_t inc); -extern gpr_stats_inc_type gpr_stats_inc_import; -#define gpr_stats_inc gpr_stats_inc_import -typedef intptr_t(*gpr_stats_read_type)(const gpr_stats_counter *c); -extern gpr_stats_read_type gpr_stats_read_import; -#define gpr_stats_read gpr_stats_read_import -typedef gpr_timespec(*gpr_time_0_type)(gpr_clock_type type); -extern gpr_time_0_type gpr_time_0_import; -#define gpr_time_0 gpr_time_0_import -typedef gpr_timespec(*gpr_inf_future_type)(gpr_clock_type type); -extern gpr_inf_future_type gpr_inf_future_import; -#define gpr_inf_future gpr_inf_future_import -typedef gpr_timespec(*gpr_inf_past_type)(gpr_clock_type type); -extern gpr_inf_past_type gpr_inf_past_import; -#define gpr_inf_past gpr_inf_past_import -typedef void(*gpr_time_init_type)(void); -extern gpr_time_init_type gpr_time_init_import; -#define gpr_time_init gpr_time_init_import -typedef gpr_timespec(*gpr_now_type)(gpr_clock_type clock); -extern gpr_now_type gpr_now_import; -#define gpr_now gpr_now_import -typedef gpr_timespec(*gpr_convert_clock_type_type)(gpr_timespec t, gpr_clock_type target_clock); -extern gpr_convert_clock_type_type gpr_convert_clock_type_import; -#define gpr_convert_clock_type gpr_convert_clock_type_import -typedef int(*gpr_time_cmp_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_cmp_type gpr_time_cmp_import; -#define gpr_time_cmp gpr_time_cmp_import -typedef gpr_timespec(*gpr_time_max_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_max_type gpr_time_max_import; -#define gpr_time_max gpr_time_max_import -typedef gpr_timespec(*gpr_time_min_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_min_type gpr_time_min_import; -#define gpr_time_min gpr_time_min_import -typedef gpr_timespec(*gpr_time_add_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_add_type gpr_time_add_import; -#define gpr_time_add gpr_time_add_import -typedef gpr_timespec(*gpr_time_sub_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_sub_type gpr_time_sub_import; -#define gpr_time_sub gpr_time_sub_import -typedef gpr_timespec(*gpr_time_from_micros_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_micros_type gpr_time_from_micros_import; -#define gpr_time_from_micros gpr_time_from_micros_import -typedef gpr_timespec(*gpr_time_from_nanos_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_nanos_type gpr_time_from_nanos_import; -#define gpr_time_from_nanos gpr_time_from_nanos_import -typedef gpr_timespec(*gpr_time_from_millis_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_millis_type gpr_time_from_millis_import; -#define gpr_time_from_millis gpr_time_from_millis_import -typedef gpr_timespec(*gpr_time_from_seconds_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_seconds_type gpr_time_from_seconds_import; -#define gpr_time_from_seconds gpr_time_from_seconds_import -typedef gpr_timespec(*gpr_time_from_minutes_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_minutes_type gpr_time_from_minutes_import; -#define gpr_time_from_minutes gpr_time_from_minutes_import -typedef gpr_timespec(*gpr_time_from_hours_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_hours_type gpr_time_from_hours_import; -#define gpr_time_from_hours gpr_time_from_hours_import -typedef int32_t(*gpr_time_to_millis_type)(gpr_timespec timespec); -extern gpr_time_to_millis_type gpr_time_to_millis_import; -#define gpr_time_to_millis gpr_time_to_millis_import -typedef int(*gpr_time_similar_type)(gpr_timespec a, gpr_timespec b, gpr_timespec threshold); -extern gpr_time_similar_type gpr_time_similar_import; -#define gpr_time_similar gpr_time_similar_import -typedef void(*gpr_sleep_until_type)(gpr_timespec until); -extern gpr_sleep_until_type gpr_sleep_until_import; -#define gpr_sleep_until gpr_sleep_until_import -typedef double(*gpr_timespec_to_micros_type)(gpr_timespec t); -extern gpr_timespec_to_micros_type gpr_timespec_to_micros_import; -#define gpr_timespec_to_micros gpr_timespec_to_micros_import -typedef gpr_avl(*gpr_avl_create_type)(const gpr_avl_vtable *vtable); -extern gpr_avl_create_type gpr_avl_create_import; -#define gpr_avl_create gpr_avl_create_import -typedef gpr_avl(*gpr_avl_ref_type)(gpr_avl avl); -extern gpr_avl_ref_type gpr_avl_ref_import; -#define gpr_avl_ref gpr_avl_ref_import -typedef void(*gpr_avl_unref_type)(gpr_avl avl); -extern gpr_avl_unref_type gpr_avl_unref_import; -#define gpr_avl_unref gpr_avl_unref_import -typedef gpr_avl(*gpr_avl_add_type)(gpr_avl avl, void *key, void *value); -extern gpr_avl_add_type gpr_avl_add_import; -#define gpr_avl_add gpr_avl_add_import -typedef gpr_avl(*gpr_avl_remove_type)(gpr_avl avl, void *key); -extern gpr_avl_remove_type gpr_avl_remove_import; -#define gpr_avl_remove gpr_avl_remove_import -typedef void *(*gpr_avl_get_type)(gpr_avl avl, void *key); -extern gpr_avl_get_type gpr_avl_get_import; -#define gpr_avl_get gpr_avl_get_import -typedef int(*gpr_avl_maybe_get_type)(gpr_avl avl, void *key, void **value); -extern gpr_avl_maybe_get_type gpr_avl_maybe_get_import; -#define gpr_avl_maybe_get gpr_avl_maybe_get_import -typedef int(*gpr_avl_is_empty_type)(gpr_avl avl); -extern gpr_avl_is_empty_type gpr_avl_is_empty_import; -#define gpr_avl_is_empty gpr_avl_is_empty_import -typedef gpr_cmdline *(*gpr_cmdline_create_type)(const char *description); -extern gpr_cmdline_create_type gpr_cmdline_create_import; -#define gpr_cmdline_create gpr_cmdline_create_import -typedef void(*gpr_cmdline_add_int_type)(gpr_cmdline *cl, const char *name, const char *help, int *value); -extern gpr_cmdline_add_int_type gpr_cmdline_add_int_import; -#define gpr_cmdline_add_int gpr_cmdline_add_int_import -typedef void(*gpr_cmdline_add_flag_type)(gpr_cmdline *cl, const char *name, const char *help, int *value); -extern gpr_cmdline_add_flag_type gpr_cmdline_add_flag_import; -#define gpr_cmdline_add_flag gpr_cmdline_add_flag_import -typedef void(*gpr_cmdline_add_string_type)(gpr_cmdline *cl, const char *name, const char *help, char **value); -extern gpr_cmdline_add_string_type gpr_cmdline_add_string_import; -#define gpr_cmdline_add_string gpr_cmdline_add_string_import -typedef void(*gpr_cmdline_on_extra_arg_type)(gpr_cmdline *cl, const char *name, const char *help, void (*on_extra_arg)(void *user_data, const char *arg), void *user_data); -extern gpr_cmdline_on_extra_arg_type gpr_cmdline_on_extra_arg_import; -#define gpr_cmdline_on_extra_arg gpr_cmdline_on_extra_arg_import -typedef void(*gpr_cmdline_set_survive_failure_type)(gpr_cmdline *cl); -extern gpr_cmdline_set_survive_failure_type gpr_cmdline_set_survive_failure_import; -#define gpr_cmdline_set_survive_failure gpr_cmdline_set_survive_failure_import -typedef int(*gpr_cmdline_parse_type)(gpr_cmdline *cl, int argc, char **argv); -extern gpr_cmdline_parse_type gpr_cmdline_parse_import; -#define gpr_cmdline_parse gpr_cmdline_parse_import -typedef void(*gpr_cmdline_destroy_type)(gpr_cmdline *cl); -extern gpr_cmdline_destroy_type gpr_cmdline_destroy_import; -#define gpr_cmdline_destroy gpr_cmdline_destroy_import -typedef char *(*gpr_cmdline_usage_string_type)(gpr_cmdline *cl, const char *argv0); -extern gpr_cmdline_usage_string_type gpr_cmdline_usage_string_import; -#define gpr_cmdline_usage_string gpr_cmdline_usage_string_import -typedef unsigned(*gpr_cpu_num_cores_type)(void); -extern gpr_cpu_num_cores_type gpr_cpu_num_cores_import; -#define gpr_cpu_num_cores gpr_cpu_num_cores_import -typedef unsigned(*gpr_cpu_current_cpu_type)(void); -extern gpr_cpu_current_cpu_type gpr_cpu_current_cpu_import; -#define gpr_cpu_current_cpu gpr_cpu_current_cpu_import -typedef gpr_histogram *(*gpr_histogram_create_type)(double resolution, double max_bucket_start); -extern gpr_histogram_create_type gpr_histogram_create_import; -#define gpr_histogram_create gpr_histogram_create_import -typedef void(*gpr_histogram_destroy_type)(gpr_histogram *h); -extern gpr_histogram_destroy_type gpr_histogram_destroy_import; -#define gpr_histogram_destroy gpr_histogram_destroy_import -typedef void(*gpr_histogram_add_type)(gpr_histogram *h, double x); -extern gpr_histogram_add_type gpr_histogram_add_import; -#define gpr_histogram_add gpr_histogram_add_import -typedef int(*gpr_histogram_merge_type)(gpr_histogram *dst, const gpr_histogram *src); -extern gpr_histogram_merge_type gpr_histogram_merge_import; -#define gpr_histogram_merge gpr_histogram_merge_import -typedef double(*gpr_histogram_percentile_type)(gpr_histogram *histogram, double percentile); -extern gpr_histogram_percentile_type gpr_histogram_percentile_import; -#define gpr_histogram_percentile gpr_histogram_percentile_import -typedef double(*gpr_histogram_mean_type)(gpr_histogram *histogram); -extern gpr_histogram_mean_type gpr_histogram_mean_import; -#define gpr_histogram_mean gpr_histogram_mean_import -typedef double(*gpr_histogram_stddev_type)(gpr_histogram *histogram); -extern gpr_histogram_stddev_type gpr_histogram_stddev_import; -#define gpr_histogram_stddev gpr_histogram_stddev_import -typedef double(*gpr_histogram_variance_type)(gpr_histogram *histogram); -extern gpr_histogram_variance_type gpr_histogram_variance_import; -#define gpr_histogram_variance gpr_histogram_variance_import -typedef double(*gpr_histogram_maximum_type)(gpr_histogram *histogram); -extern gpr_histogram_maximum_type gpr_histogram_maximum_import; -#define gpr_histogram_maximum gpr_histogram_maximum_import -typedef double(*gpr_histogram_minimum_type)(gpr_histogram *histogram); -extern gpr_histogram_minimum_type gpr_histogram_minimum_import; -#define gpr_histogram_minimum gpr_histogram_minimum_import -typedef double(*gpr_histogram_count_type)(gpr_histogram *histogram); -extern gpr_histogram_count_type gpr_histogram_count_import; -#define gpr_histogram_count gpr_histogram_count_import -typedef double(*gpr_histogram_sum_type)(gpr_histogram *histogram); -extern gpr_histogram_sum_type gpr_histogram_sum_import; -#define gpr_histogram_sum gpr_histogram_sum_import -typedef double(*gpr_histogram_sum_of_squares_type)(gpr_histogram *histogram); -extern gpr_histogram_sum_of_squares_type gpr_histogram_sum_of_squares_import; -#define gpr_histogram_sum_of_squares gpr_histogram_sum_of_squares_import -typedef const uint32_t *(*gpr_histogram_get_contents_type)(gpr_histogram *histogram, size_t *count); -extern gpr_histogram_get_contents_type gpr_histogram_get_contents_import; -#define gpr_histogram_get_contents gpr_histogram_get_contents_import -typedef void(*gpr_histogram_merge_contents_type)(gpr_histogram *histogram, const uint32_t *data, size_t data_count, double min_seen, double max_seen, double sum, double sum_of_squares, double count); -extern gpr_histogram_merge_contents_type gpr_histogram_merge_contents_import; -#define gpr_histogram_merge_contents gpr_histogram_merge_contents_import -typedef int(*gpr_join_host_port_type)(char **out, const char *host, int port); -extern gpr_join_host_port_type gpr_join_host_port_import; -#define gpr_join_host_port gpr_join_host_port_import -typedef int(*gpr_split_host_port_type)(const char *name, char **host, char **port); -extern gpr_split_host_port_type gpr_split_host_port_import; -#define gpr_split_host_port gpr_split_host_port_import -typedef char *(*gpr_format_message_type)(int messageid); -extern gpr_format_message_type gpr_format_message_import; -#define gpr_format_message gpr_format_message_import -typedef char *(*gpr_strdup_type)(const char *src); -extern gpr_strdup_type gpr_strdup_import; -#define gpr_strdup gpr_strdup_import -typedef int(*gpr_asprintf_type)(char **strp, const char *format, ...) GPRC_PRINT_FORMAT_CHECK(2, 3); -extern gpr_asprintf_type gpr_asprintf_import; -#define gpr_asprintf gpr_asprintf_import -typedef const char *(*gpr_subprocess_binary_extension_type)(); -extern gpr_subprocess_binary_extension_type gpr_subprocess_binary_extension_import; -#define gpr_subprocess_binary_extension gpr_subprocess_binary_extension_import -typedef gpr_subprocess *(*gpr_subprocess_create_type)(int argc, const char **argv); -extern gpr_subprocess_create_type gpr_subprocess_create_import; -#define gpr_subprocess_create gpr_subprocess_create_import -typedef void(*gpr_subprocess_destroy_type)(gpr_subprocess *p); -extern gpr_subprocess_destroy_type gpr_subprocess_destroy_import; -#define gpr_subprocess_destroy gpr_subprocess_destroy_import -typedef int(*gpr_subprocess_join_type)(gpr_subprocess *p); -extern gpr_subprocess_join_type gpr_subprocess_join_import; -#define gpr_subprocess_join gpr_subprocess_join_import -typedef void(*gpr_subprocess_interrupt_type)(gpr_subprocess *p); -extern gpr_subprocess_interrupt_type gpr_subprocess_interrupt_import; -#define gpr_subprocess_interrupt gpr_subprocess_interrupt_import -typedef int(*gpr_thd_new_type)(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg, const gpr_thd_options *options); -extern gpr_thd_new_type gpr_thd_new_import; -#define gpr_thd_new gpr_thd_new_import -typedef gpr_thd_options(*gpr_thd_options_default_type)(void); -extern gpr_thd_options_default_type gpr_thd_options_default_import; -#define gpr_thd_options_default gpr_thd_options_default_import -typedef void(*gpr_thd_options_set_detached_type)(gpr_thd_options *options); -extern gpr_thd_options_set_detached_type gpr_thd_options_set_detached_import; -#define gpr_thd_options_set_detached gpr_thd_options_set_detached_import -typedef void(*gpr_thd_options_set_joinable_type)(gpr_thd_options *options); -extern gpr_thd_options_set_joinable_type gpr_thd_options_set_joinable_import; -#define gpr_thd_options_set_joinable gpr_thd_options_set_joinable_import -typedef int(*gpr_thd_options_is_detached_type)(const gpr_thd_options *options); -extern gpr_thd_options_is_detached_type gpr_thd_options_is_detached_import; -#define gpr_thd_options_is_detached gpr_thd_options_is_detached_import -typedef int(*gpr_thd_options_is_joinable_type)(const gpr_thd_options *options); -extern gpr_thd_options_is_joinable_type gpr_thd_options_is_joinable_import; -#define gpr_thd_options_is_joinable gpr_thd_options_is_joinable_import -typedef gpr_thd_id(*gpr_thd_currentid_type)(void); -extern gpr_thd_currentid_type gpr_thd_currentid_import; -#define gpr_thd_currentid gpr_thd_currentid_import -typedef void(*gpr_thd_join_type)(gpr_thd_id t); -extern gpr_thd_join_type gpr_thd_join_import; -#define gpr_thd_join gpr_thd_join_import - -#ifdef __cplusplus -extern "C" { -#endif /* __cpluslus */ - -void pygrpc_load_imports(HMODULE library); - -#ifdef __cplusplus -} -#endif /* __cpluslus */ - -#else /* !GPR_WINDOWS */ - -#include <grpc/byte_buffer.h> -#include <grpc/byte_buffer_reader.h> -#include <grpc/compression.h> -#include <grpc/grpc.h> -#include <grpc/grpc_security.h> -#include <grpc/support/alloc.h> -#include <grpc/support/slice.h> -#include <grpc/support/time.h> -#include <grpc/status.h> - -#endif /* !GPR_WINDOWS */ - -#endif diff --git a/src/python/grpcio/grpc/_cython/loader.c b/src/python/grpcio/grpc/_cython/loader.c deleted file mode 100644 index 86b70dbb02..0000000000 --- a/src/python/grpcio/grpc/_cython/loader.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <Python.h> -#include "loader.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cpluslus */ - -#if GPR_WINDOWS - -int pygrpc_load_core(char *path) { - HMODULE grpc_c; -#ifdef GPR_ARCH_32 - /* Close your eyes for a moment, it'll all be over soon. */ - char *six = strrchr(path, '6'); - *six++ = '3'; - *six = '2'; -#endif - grpc_c = LoadLibraryA(path); - if (grpc_c) { - pygrpc_load_imports(grpc_c); - return 1; - } - - return 0; -} - -#else - -int pygrpc_load_core(char *path) { return 1; } - -#endif /* !GPR_WINDOWS */ - -// Cython doesn't have Py_AtExit bindings, so we call the C_API directly -int pygrpc_initialize_core(void) { - grpc_init(); - return Py_AtExit(grpc_shutdown) < 0 ? 0 : 1; -} - -#ifdef __cplusplus -} -#endif /* __cpluslus */ - diff --git a/src/python/grpcio/grpc/_cython/loader.h b/src/python/grpcio/grpc/_cython/loader.h deleted file mode 100644 index eb4b1a1b01..0000000000 --- a/src/python/grpcio/grpc/_cython/loader.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef PYGRPC_LOADER_H_ -#define PYGRPC_LOADER_H_ - -#include "imports.generated.h" - -/* Additional inclusions not covered by "imports.generated.h" */ -#include <grpc/byte_buffer_reader.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cpluslus */ - -/* Attempts to load the core if necessary, and return non-zero upon succes. */ -int pygrpc_load_core(char *path); - -/* Initializes grpc and registers grpc_shutdown() to be called right before - * interpreter exit. Returns non-zero upon success. - */ -int pygrpc_initialize_core(void); - -#ifdef __cplusplus -} -#endif /* __cpluslus */ - -#endif /* GRPC_RB_BYTE_BUFFER_H_ */ - diff --git a/src/python/grpcio/grpc/_links/_constants.py b/src/python/grpcio/grpc/_links/_constants.py deleted file mode 100644 index 117fc5a639..0000000000 --- a/src/python/grpcio/grpc/_links/_constants.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Constants for use within this package.""" - -from grpc._adapter import _intermediary_low -from grpc.beta import interfaces as beta_interfaces - -LOW_STATUS_CODE_TO_HIGH_STATUS_CODE = { - low: high for low, high in zip( - _intermediary_low.Code, beta_interfaces.StatusCode) -} - -HIGH_STATUS_CODE_TO_LOW_STATUS_CODE = { - high: low for low, high in LOW_STATUS_CODE_TO_HIGH_STATUS_CODE.items() -} diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py deleted file mode 100644 index 003653e1c8..0000000000 --- a/src/python/grpcio/grpc/_links/invocation.py +++ /dev/null @@ -1,453 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""The RPC-invocation-side bridge between RPC Framework and GRPC-on-the-wire.""" - -import abc -import enum -import logging -import threading -import time - -import six - -from grpc._adapter import _intermediary_low -from grpc._links import _constants -from grpc.beta import interfaces as beta_interfaces -from grpc.framework.foundation import activated -from grpc.framework.foundation import logging_pool -from grpc.framework.foundation import relay -from grpc.framework.interfaces.links import links - -_IDENTITY = lambda x: x - -_STOP = _intermediary_low.Event.Kind.STOP -_WRITE = _intermediary_low.Event.Kind.WRITE_ACCEPTED -_COMPLETE = _intermediary_low.Event.Kind.COMPLETE_ACCEPTED -_READ = _intermediary_low.Event.Kind.READ_ACCEPTED -_METADATA = _intermediary_low.Event.Kind.METADATA_ACCEPTED -_FINISH = _intermediary_low.Event.Kind.FINISH - - -@enum.unique -class _Read(enum.Enum): - AWAITING_METADATA = 'awaiting metadata' - READING = 'reading' - AWAITING_ALLOWANCE = 'awaiting allowance' - CLOSED = 'closed' - - -@enum.unique -class _HighWrite(enum.Enum): - OPEN = 'open' - CLOSED = 'closed' - - -@enum.unique -class _LowWrite(enum.Enum): - OPEN = 'OPEN' - ACTIVE = 'ACTIVE' - CLOSED = 'CLOSED' - - -class _Context(beta_interfaces.GRPCInvocationContext): - - def __init__(self): - self._lock = threading.Lock() - self._disable_next_compression = False - - def disable_next_request_compression(self): - with self._lock: - self._disable_next_compression = True - - def next_compression_disabled(self): - with self._lock: - disabled = self._disable_next_compression - self._disable_next_compression = False - return disabled - - -class _RPCState(object): - - def __init__( - self, call, request_serializer, response_deserializer, sequence_number, - read, allowance, high_write, low_write, due, context): - self.call = call - self.request_serializer = request_serializer - self.response_deserializer = response_deserializer - self.sequence_number = sequence_number - self.read = read - self.allowance = allowance - self.high_write = high_write - self.low_write = low_write - self.due = due - self.context = context - - -def _no_longer_due(kind, rpc_state, key, rpc_states): - rpc_state.due.remove(kind) - if not rpc_state.due: - del rpc_states[key] - - -class _Kernel(object): - - def __init__( - self, channel, host, metadata_transformer, request_serializers, - response_deserializers, ticket_relay): - self._lock = threading.Lock() - self._channel = channel - self._host = host - self._metadata_transformer = metadata_transformer - self._request_serializers = request_serializers - self._response_deserializers = response_deserializers - self._relay = ticket_relay - - self._completion_queue = None - self._rpc_states = {} - self._pool = None - - def _on_write_event(self, operation_id, unused_event, rpc_state): - if rpc_state.high_write is _HighWrite.CLOSED: - rpc_state.call.complete(operation_id) - rpc_state.due.add(_COMPLETE) - rpc_state.due.remove(_WRITE) - rpc_state.low_write = _LowWrite.CLOSED - else: - ticket = links.Ticket( - operation_id, rpc_state.sequence_number, None, None, None, None, 1, - None, None, None, None, None, None, None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) - rpc_state.low_write = _LowWrite.OPEN - _no_longer_due(_WRITE, rpc_state, operation_id, self._rpc_states) - - def _on_read_event(self, operation_id, event, rpc_state): - if event.bytes is None or _FINISH not in rpc_state.due: - rpc_state.read = _Read.CLOSED - _no_longer_due(_READ, rpc_state, operation_id, self._rpc_states) - else: - if 0 < rpc_state.allowance: - rpc_state.allowance -= 1 - rpc_state.call.read(operation_id) - else: - rpc_state.read = _Read.AWAITING_ALLOWANCE - _no_longer_due(_READ, rpc_state, operation_id, self._rpc_states) - ticket = links.Ticket( - operation_id, rpc_state.sequence_number, None, None, None, None, None, - None, rpc_state.response_deserializer(event.bytes), None, None, None, - None, None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) - - def _on_metadata_event(self, operation_id, event, rpc_state): - if _FINISH in rpc_state.due: - rpc_state.allowance -= 1 - rpc_state.call.read(operation_id) - rpc_state.read = _Read.READING - rpc_state.due.add(_READ) - rpc_state.due.remove(_METADATA) - ticket = links.Ticket( - operation_id, rpc_state.sequence_number, None, None, - links.Ticket.Subscription.FULL, None, None, event.metadata, None, - None, None, None, None, None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) - else: - _no_longer_due(_METADATA, rpc_state, operation_id, self._rpc_states) - - def _on_finish_event(self, operation_id, event, rpc_state): - _no_longer_due(_FINISH, rpc_state, operation_id, self._rpc_states) - if event.status.code == _intermediary_low.Code.OK: - termination = links.Ticket.Termination.COMPLETION - elif event.status.code == _intermediary_low.Code.CANCELLED: - termination = links.Ticket.Termination.CANCELLATION - elif event.status.code == _intermediary_low.Code.DEADLINE_EXCEEDED: - termination = links.Ticket.Termination.EXPIRATION - elif event.status.code == _intermediary_low.Code.UNIMPLEMENTED: - termination = links.Ticket.Termination.REMOTE_FAILURE - elif event.status.code == _intermediary_low.Code.UNKNOWN: - termination = links.Ticket.Termination.LOCAL_FAILURE - else: - termination = links.Ticket.Termination.TRANSMISSION_FAILURE - code = _constants.LOW_STATUS_CODE_TO_HIGH_STATUS_CODE[event.status.code] - ticket = links.Ticket( - operation_id, rpc_state.sequence_number, None, None, None, None, None, - None, None, event.metadata, code, event.status.details, termination, - None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) - - def _spin(self, completion_queue): - while True: - event = completion_queue.get(None) - with self._lock: - rpc_state = self._rpc_states.get(event.tag, None) - if event.kind is _STOP: - pass - elif event.kind is _WRITE: - self._on_write_event(event.tag, event, rpc_state) - elif event.kind is _METADATA: - self._on_metadata_event(event.tag, event, rpc_state) - elif event.kind is _READ: - self._on_read_event(event.tag, event, rpc_state) - elif event.kind is _FINISH: - self._on_finish_event(event.tag, event, rpc_state) - elif event.kind is _COMPLETE: - _no_longer_due(_COMPLETE, rpc_state, event.tag, self._rpc_states) - else: - logging.error('Illegal RPC event! %s', (event,)) - - if self._completion_queue is None and not self._rpc_states: - completion_queue.stop() - return - - def _invoke( - self, operation_id, group, method, initial_metadata, payload, termination, - timeout, allowance, options): - """Invoke an RPC. - - Args: - operation_id: Any object to be used as an operation ID for the RPC. - group: The group to which the RPC method belongs. - method: The RPC method name. - initial_metadata: The initial metadata object for the RPC. - payload: A payload object for the RPC or None if no payload was given at - invocation-time. - termination: A links.Ticket.Termination value or None indicated whether or - not more writes will follow from this side of the RPC. - timeout: A duration of time in seconds to allow for the RPC. - allowance: The number of payloads (beyond the free first one) that the - local ticket exchange mate has granted permission to be read. - options: A beta_interfaces.GRPCCallOptions value or None. - """ - if termination is links.Ticket.Termination.COMPLETION: - high_write = _HighWrite.CLOSED - elif termination is None: - high_write = _HighWrite.OPEN - else: - return - - transformed_initial_metadata = self._metadata_transformer(initial_metadata) - request_serializer = self._request_serializers.get( - (group, method), _IDENTITY) - response_deserializer = self._response_deserializers.get( - (group, method), _IDENTITY) - - call = _intermediary_low.Call( - self._channel, self._completion_queue, '/%s/%s' % (group, method), - self._host, time.time() + timeout) - if options is not None and options.credentials is not None: - call.set_credentials(options.credentials._low_credentials) - if transformed_initial_metadata is not None: - for metadata_key, metadata_value in transformed_initial_metadata: - call.add_metadata(metadata_key, metadata_value) - call.invoke(self._completion_queue, operation_id, operation_id) - if payload is None: - if high_write is _HighWrite.CLOSED: - call.complete(operation_id) - low_write = _LowWrite.CLOSED - due = set((_METADATA, _COMPLETE, _FINISH,)) - else: - low_write = _LowWrite.OPEN - due = set((_METADATA, _FINISH,)) - else: - if options is not None and options.disable_compression: - flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS - else: - flags = 0 - call.write(request_serializer(payload), operation_id, flags) - low_write = _LowWrite.ACTIVE - due = set((_WRITE, _METADATA, _FINISH,)) - context = _Context() - self._rpc_states[operation_id] = _RPCState( - call, request_serializer, response_deserializer, 1, - _Read.AWAITING_METADATA, 1 if allowance is None else (1 + allowance), - high_write, low_write, due, context) - protocol = links.Protocol(links.Protocol.Kind.INVOCATION_CONTEXT, context) - ticket = links.Ticket( - operation_id, 0, None, None, None, None, None, None, None, None, None, - None, None, protocol) - self._relay.add_value(ticket) - - def _advance(self, operation_id, rpc_state, payload, termination, allowance): - if payload is not None: - disable_compression = rpc_state.context.next_compression_disabled() - if disable_compression: - flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS - else: - flags = 0 - rpc_state.call.write( - rpc_state.request_serializer(payload), operation_id, flags) - rpc_state.low_write = _LowWrite.ACTIVE - rpc_state.due.add(_WRITE) - - if allowance is not None: - if rpc_state.read is _Read.AWAITING_ALLOWANCE: - rpc_state.allowance += allowance - 1 - rpc_state.call.read(operation_id) - rpc_state.read = _Read.READING - rpc_state.due.add(_READ) - else: - rpc_state.allowance += allowance - - if termination is links.Ticket.Termination.COMPLETION: - rpc_state.high_write = _HighWrite.CLOSED - if rpc_state.low_write is _LowWrite.OPEN: - rpc_state.call.complete(operation_id) - rpc_state.due.add(_COMPLETE) - rpc_state.low_write = _LowWrite.CLOSED - elif termination is not None: - rpc_state.call.cancel() - - def add_ticket(self, ticket): - with self._lock: - if ticket.sequence_number == 0: - if self._completion_queue is None: - logging.error('Received invocation ticket %s after stop!', ticket) - else: - if (ticket.protocol is not None and - ticket.protocol.kind is links.Protocol.Kind.CALL_OPTION): - grpc_call_options = ticket.protocol.value - else: - grpc_call_options = None - self._invoke( - ticket.operation_id, ticket.group, ticket.method, - ticket.initial_metadata, ticket.payload, ticket.termination, - ticket.timeout, ticket.allowance, grpc_call_options) - else: - rpc_state = self._rpc_states.get(ticket.operation_id) - if rpc_state is not None: - self._advance( - ticket.operation_id, rpc_state, ticket.payload, - ticket.termination, ticket.allowance) - - def start(self): - """Starts this object. - - This method must be called before attempting to exchange tickets with this - object. - """ - with self._lock: - self._completion_queue = _intermediary_low.CompletionQueue() - self._pool = logging_pool.pool(1) - self._pool.submit(self._spin, self._completion_queue) - - def stop(self): - """Stops this object. - - This method must be called for proper termination of this object, and no - attempts to exchange tickets with this object may be made after this method - has been called. - """ - with self._lock: - if not self._rpc_states: - self._completion_queue.stop() - self._completion_queue = None - pool = self._pool - pool.shutdown(wait=True) - - -class InvocationLink(six.with_metaclass(abc.ABCMeta, links.Link, activated.Activated)): - """A links.Link for use on the invocation-side of a gRPC connection. - - Implementations of this interface are only valid for use when activated. - """ - - -class _InvocationLink(InvocationLink): - - def __init__( - self, channel, host, metadata_transformer, request_serializers, - response_deserializers): - self._relay = relay.relay(None) - self._kernel = _Kernel( - channel, host, - _IDENTITY if metadata_transformer is None else metadata_transformer, - {} if request_serializers is None else request_serializers, - {} if response_deserializers is None else response_deserializers, - self._relay) - - def _start(self): - self._relay.start() - self._kernel.start() - return self - - def _stop(self): - self._kernel.stop() - self._relay.stop() - - def accept_ticket(self, ticket): - """See links.Link.accept_ticket for specification.""" - self._kernel.add_ticket(ticket) - - def join_link(self, link): - """See links.Link.join_link for specification.""" - self._relay.set_behavior(link.accept_ticket) - - def __enter__(self): - """See activated.Activated.__enter__ for specification.""" - return self._start() - - def __exit__(self, exc_type, exc_val, exc_tb): - """See activated.Activated.__exit__ for specification.""" - self._stop() - return False - - def start(self): - """See activated.Activated.start for specification.""" - return self._start() - - def stop(self): - """See activated.Activated.stop for specification.""" - self._stop() - - -def invocation_link( - channel, host, metadata_transformer, request_serializers, - response_deserializers): - """Creates an InvocationLink. - - Args: - channel: An _intermediary_low.Channel for use by the link. - host: The host to specify when invoking RPCs. - metadata_transformer: A callable that takes an invocation-side initial - metadata value and returns another metadata value to send in its place. - May be None. - request_serializers: A dict from group-method pair to request object - serialization behavior. - response_deserializers: A dict from group-method pair to response object - deserialization behavior. - - Returns: - An InvocationLink. - """ - return _InvocationLink( - channel, host, metadata_transformer, request_serializers, - response_deserializers) diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py deleted file mode 100644 index 5fc4994ca0..0000000000 --- a/src/python/grpcio/grpc/_links/service.py +++ /dev/null @@ -1,509 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""The RPC-service-side bridge between RPC Framework and GRPC-on-the-wire.""" - -import abc -import enum -import logging -import threading -import six -import time - -from grpc._adapter import _intermediary_low -from grpc._links import _constants -from grpc.beta import interfaces as beta_interfaces -from grpc.framework.foundation import logging_pool -from grpc.framework.foundation import relay -from grpc.framework.interfaces.links import links - -_IDENTITY = lambda x: x - -_TERMINATION_KIND_TO_CODE = { - links.Ticket.Termination.COMPLETION: _intermediary_low.Code.OK, - links.Ticket.Termination.CANCELLATION: _intermediary_low.Code.CANCELLED, - links.Ticket.Termination.EXPIRATION: - _intermediary_low.Code.DEADLINE_EXCEEDED, - links.Ticket.Termination.SHUTDOWN: _intermediary_low.Code.UNAVAILABLE, - links.Ticket.Termination.RECEPTION_FAILURE: _intermediary_low.Code.INTERNAL, - links.Ticket.Termination.TRANSMISSION_FAILURE: - _intermediary_low.Code.INTERNAL, - links.Ticket.Termination.LOCAL_FAILURE: _intermediary_low.Code.UNKNOWN, - links.Ticket.Termination.REMOTE_FAILURE: _intermediary_low.Code.UNKNOWN, -} - -_STOP = _intermediary_low.Event.Kind.STOP -_WRITE = _intermediary_low.Event.Kind.WRITE_ACCEPTED -_COMPLETE = _intermediary_low.Event.Kind.COMPLETE_ACCEPTED -_SERVICE = _intermediary_low.Event.Kind.SERVICE_ACCEPTED -_READ = _intermediary_low.Event.Kind.READ_ACCEPTED -_FINISH = _intermediary_low.Event.Kind.FINISH - - -@enum.unique -class _Read(enum.Enum): - READING = 'reading' - # TODO(issue 2916): This state will again be necessary after eliminating the - # "early_read" field of _RPCState and going back to only reading when granted - # allowance to read. - # AWAITING_ALLOWANCE = 'awaiting allowance' - CLOSED = 'closed' - - -@enum.unique -class _HighWrite(enum.Enum): - OPEN = 'open' - CLOSED = 'closed' - - -@enum.unique -class _LowWrite(enum.Enum): - """The possible categories of low-level write state.""" - - OPEN = 'OPEN' - ACTIVE = 'ACTIVE' - CLOSED = 'CLOSED' - - -class _Context(beta_interfaces.GRPCServicerContext): - - def __init__(self, call): - self._lock = threading.Lock() - self._call = call - self._disable_next_compression = False - - def peer(self): - with self._lock: - return self._call.peer() - - def disable_next_response_compression(self): - with self._lock: - self._disable_next_compression = True - - def next_compression_disabled(self): - with self._lock: - disabled = self._disable_next_compression - self._disable_next_compression = False - return disabled - - -class _RPCState(object): - - def __init__( - self, request_deserializer, response_serializer, sequence_number, read, - early_read, allowance, high_write, low_write, premetadataed, - terminal_metadata, code, message, due, context): - self.request_deserializer = request_deserializer - self.response_serializer = response_serializer - self.sequence_number = sequence_number - self.read = read - # TODO(issue 2916): Eliminate this by eliminating the necessity of calling - # call.read just to advance the RPC. - self.early_read = early_read # A raw (not deserialized) read. - self.allowance = allowance - self.high_write = high_write - self.low_write = low_write - self.premetadataed = premetadataed - self.terminal_metadata = terminal_metadata - self.code = code - self.message = message - self.due = due - self.context = context - - -def _no_longer_due(kind, rpc_state, key, rpc_states): - rpc_state.due.remove(kind) - if not rpc_state.due: - del rpc_states[key] - - -def _metadatafy(call, metadata): - for metadata_key, metadata_value in metadata: - call.add_metadata(metadata_key, metadata_value) - - -def _status(termination_kind, high_code, details): - low_details = b'' if details is None else details - if high_code is None: - low_code = _TERMINATION_KIND_TO_CODE[termination_kind] - else: - low_code = _constants.HIGH_STATUS_CODE_TO_LOW_STATUS_CODE[high_code] - return _intermediary_low.Status(low_code, low_details) - - -class _Kernel(object): - - def __init__(self, request_deserializers, response_serializers, ticket_relay): - self._lock = threading.Lock() - self._request_deserializers = request_deserializers - self._response_serializers = response_serializers - self._relay = ticket_relay - - self._completion_queue = None - self._due = set() - self._server = None - self._rpc_states = {} - self._pool = None - - def _on_service_acceptance_event(self, event, server): - server.service(None) - - service_acceptance = event.service_acceptance - call = service_acceptance.call - call.accept(self._completion_queue, call) - try: - service_method = service_acceptance.method - if six.PY3: - service_method = service_method.decode('latin1') - group, method = service_method.split('/')[1:3] - except ValueError: - logging.info('Illegal path "%s"!', service_acceptance.method) - return - request_deserializer = self._request_deserializers.get( - (group, method), _IDENTITY) - response_serializer = self._response_serializers.get( - (group, method), _IDENTITY) - - call.read(call) - context = _Context(call) - self._rpc_states[call] = _RPCState( - request_deserializer, response_serializer, 1, _Read.READING, None, 1, - _HighWrite.OPEN, _LowWrite.OPEN, False, None, None, None, - set((_READ, _FINISH,)), context) - protocol = links.Protocol(links.Protocol.Kind.SERVICER_CONTEXT, context) - ticket = links.Ticket( - call, 0, group, method, links.Ticket.Subscription.FULL, - service_acceptance.deadline - time.time(), None, event.metadata, None, - None, None, None, None, protocol) - self._relay.add_value(ticket) - - def _on_read_event(self, event): - call = event.tag - rpc_state = self._rpc_states[call] - - if event.bytes is None: - rpc_state.read = _Read.CLOSED - payload = None - termination = links.Ticket.Termination.COMPLETION - _no_longer_due(_READ, rpc_state, call, self._rpc_states) - else: - if 0 < rpc_state.allowance: - payload = rpc_state.request_deserializer(event.bytes) - termination = None - rpc_state.allowance -= 1 - call.read(call) - else: - rpc_state.early_read = event.bytes - _no_longer_due(_READ, rpc_state, call, self._rpc_states) - return - # TODO(issue 2916): Instead of returning: - # rpc_state.read = _Read.AWAITING_ALLOWANCE - ticket = links.Ticket( - call, rpc_state.sequence_number, None, None, None, None, None, None, - payload, None, None, None, termination, None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) - - def _on_write_event(self, event): - call = event.tag - rpc_state = self._rpc_states[call] - - if rpc_state.high_write is _HighWrite.CLOSED: - if rpc_state.terminal_metadata is not None: - _metadatafy(call, rpc_state.terminal_metadata) - status = _status( - links.Ticket.Termination.COMPLETION, rpc_state.code, - rpc_state.message) - call.status(status, call) - rpc_state.low_write = _LowWrite.CLOSED - rpc_state.due.add(_COMPLETE) - rpc_state.due.remove(_WRITE) - else: - ticket = links.Ticket( - call, rpc_state.sequence_number, None, None, None, None, 1, None, - None, None, None, None, None, None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) - rpc_state.low_write = _LowWrite.OPEN - _no_longer_due(_WRITE, rpc_state, call, self._rpc_states) - - def _on_finish_event(self, event): - call = event.tag - rpc_state = self._rpc_states[call] - _no_longer_due(_FINISH, rpc_state, call, self._rpc_states) - code = event.status.code - if code == _intermediary_low.Code.OK: - return - - if code == _intermediary_low.Code.CANCELLED: - termination = links.Ticket.Termination.CANCELLATION - elif code == _intermediary_low.Code.DEADLINE_EXCEEDED: - termination = links.Ticket.Termination.EXPIRATION - else: - termination = links.Ticket.Termination.TRANSMISSION_FAILURE - ticket = links.Ticket( - call, rpc_state.sequence_number, None, None, None, None, None, None, - None, None, None, None, termination, None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) - - def _spin(self, completion_queue, server): - while True: - event = completion_queue.get(None) - with self._lock: - if event.kind is _STOP: - self._due.remove(_STOP) - elif event.kind is _READ: - self._on_read_event(event) - elif event.kind is _WRITE: - self._on_write_event(event) - elif event.kind is _COMPLETE: - _no_longer_due( - _COMPLETE, self._rpc_states.get(event.tag), event.tag, - self._rpc_states) - elif event.kind is _intermediary_low.Event.Kind.FINISH: - self._on_finish_event(event) - elif event.kind is _SERVICE: - if self._server is None: - self._due.remove(_SERVICE) - else: - self._on_service_acceptance_event(event, server) - else: - logging.error('Illegal event! %s', (event,)) - - if not self._due and not self._rpc_states: - completion_queue.stop() - return - - def add_ticket(self, ticket): - with self._lock: - call = ticket.operation_id - rpc_state = self._rpc_states.get(call) - if rpc_state is None: - return - - if ticket.initial_metadata is not None: - _metadatafy(call, ticket.initial_metadata) - call.premetadata() - rpc_state.premetadataed = True - elif not rpc_state.premetadataed: - if (ticket.terminal_metadata is not None or - ticket.payload is not None or - ticket.termination is not None or - ticket.code is not None or - ticket.message is not None): - call.premetadata() - rpc_state.premetadataed = True - - if ticket.allowance is not None: - if rpc_state.early_read is None: - rpc_state.allowance += ticket.allowance - else: - payload = rpc_state.request_deserializer(rpc_state.early_read) - rpc_state.allowance += ticket.allowance - 1 - rpc_state.early_read = None - if rpc_state.read is _Read.READING: - call.read(call) - rpc_state.due.add(_READ) - termination = None - else: - termination = links.Ticket.Termination.COMPLETION - early_read_ticket = links.Ticket( - call, rpc_state.sequence_number, None, None, None, None, None, - None, payload, None, None, None, termination, None) - rpc_state.sequence_number += 1 - self._relay.add_value(early_read_ticket) - - if ticket.payload is not None: - disable_compression = rpc_state.context.next_compression_disabled() - if disable_compression: - flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS - else: - flags = 0 - call.write(rpc_state.response_serializer(ticket.payload), call, flags) - rpc_state.due.add(_WRITE) - rpc_state.low_write = _LowWrite.ACTIVE - - if ticket.terminal_metadata is not None: - rpc_state.terminal_metadata = ticket.terminal_metadata - if ticket.code is not None: - rpc_state.code = ticket.code - if ticket.message is not None: - rpc_state.message = ticket.message - - if ticket.termination is links.Ticket.Termination.COMPLETION: - rpc_state.high_write = _HighWrite.CLOSED - if rpc_state.low_write is _LowWrite.OPEN: - if rpc_state.terminal_metadata is not None: - _metadatafy(call, rpc_state.terminal_metadata) - status = _status( - links.Ticket.Termination.COMPLETION, rpc_state.code, - rpc_state.message) - call.status(status, call) - rpc_state.due.add(_COMPLETE) - rpc_state.low_write = _LowWrite.CLOSED - elif ticket.termination is not None: - if rpc_state.terminal_metadata is not None: - _metadatafy(call, rpc_state.terminal_metadata) - status = _status( - ticket.termination, rpc_state.code, rpc_state.message) - call.status(status, call) - rpc_state.due.add(_COMPLETE) - - def add_port(self, address, server_credentials): - with self._lock: - if self._server is None: - self._completion_queue = _intermediary_low.CompletionQueue() - self._server = _intermediary_low.Server(self._completion_queue) - if server_credentials is None: - return self._server.add_http2_addr(address) - else: - return self._server.add_secure_http2_addr(address, server_credentials) - - def start(self): - with self._lock: - if self._server is None: - self._completion_queue = _intermediary_low.CompletionQueue() - self._server = _intermediary_low.Server(self._completion_queue) - self._pool = logging_pool.pool(1) - self._pool.submit(self._spin, self._completion_queue, self._server) - self._server.start() - self._server.service(None) - self._due.add(_SERVICE) - - def begin_stop(self): - with self._lock: - self._server.stop() - self._due.add(_STOP) - self._server = None - - def end_stop(self): - with self._lock: - pool = self._pool - pool.shutdown(wait=True) - - -class ServiceLink(links.Link): - """A links.Link for use on the service-side of a gRPC connection. - - Implementations of this interface are only valid for use between calls to - their start method and one of their stop methods. - """ - - @abc.abstractmethod - def add_port(self, address, server_credentials): - """Adds a port on which to service RPCs after this link has been started. - - Args: - address: The address on which to service RPCs with a port number of zero - requesting that a port number be automatically selected and used. - server_credentials: An _intermediary_low.ServerCredentials object, or - None for insecure service. - - Returns: - An integer port on which RPCs will be serviced after this link has been - started. This is typically the same number as the port number contained - in the passed address, but will likely be different if the port number - contained in the passed address was zero. - """ - raise NotImplementedError() - - @abc.abstractmethod - def start(self): - """Starts this object. - - This method must be called before attempting to use this Link in ticket - exchange. - """ - raise NotImplementedError() - - @abc.abstractmethod - def begin_stop(self): - """Indicate imminent link stop and immediate rejection of new RPCs. - - New RPCs will be rejected as soon as this method is called, but ongoing RPCs - will be allowed to continue until they terminate. This method does not - block. - """ - raise NotImplementedError() - - @abc.abstractmethod - def end_stop(self): - """Finishes stopping this link. - - begin_stop must have been called exactly once before calling this method. - - All in-progress RPCs will be terminated immediately. - """ - raise NotImplementedError() - - -class _ServiceLink(ServiceLink): - - def __init__(self, request_deserializers, response_serializers): - self._relay = relay.relay(None) - self._kernel = _Kernel( - {} if request_deserializers is None else request_deserializers, - {} if response_serializers is None else response_serializers, - self._relay) - - def accept_ticket(self, ticket): - self._kernel.add_ticket(ticket) - - def join_link(self, link): - self._relay.set_behavior(link.accept_ticket) - - def add_port(self, address, server_credentials): - return self._kernel.add_port(address, server_credentials) - - def start(self): - self._relay.start() - return self._kernel.start() - - def begin_stop(self): - self._kernel.begin_stop() - - def end_stop(self): - self._kernel.end_stop() - self._relay.stop() - - -def service_link(request_deserializers, response_serializers): - """Creates a ServiceLink. - - Args: - request_deserializers: A dict from group-method pair to request object - deserialization behavior. - response_serializers: A dict from group-method pair to response ojbect - serialization behavior. - - Returns: - A ServiceLink. - """ - return _ServiceLink(request_deserializers, response_serializers) diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index f4c114056f..94a13bfb2f 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -157,7 +157,7 @@ def _abort(state, call, code, details): effective_details, _EMPTY_FLAGS), ) token = _SEND_STATUS_FROM_SERVER_TOKEN - call.start_batch( + call.start_server_batch( cygrpc.Operations(operations), _send_status_from_server(state, token)) state.statused = True @@ -257,7 +257,7 @@ class _Context(grpc.ServicerContext): if self._state.initial_metadata_allowed: operation = cygrpc.operation_send_initial_metadata( _common.cygrpc_metadata(initial_metadata), _EMPTY_FLAGS) - self._rpc_event.operation_call.start_batch( + self._rpc_event.operation_call.start_server_batch( cygrpc.Operations((operation,)), _send_initial_metadata(self._state)) self._state.initial_metadata_allowed = False @@ -292,7 +292,7 @@ class _RequestIterator(object): elif self._state.client is _CLOSED or self._state.statused: raise StopIteration() else: - self._call.start_batch( + self._call.start_server_batch( cygrpc.Operations((cygrpc.operation_receive_message(_EMPTY_FLAGS),)), _receive_message(self._state, self._call, self._request_deserializer)) self._state.due.add(_RECEIVE_MESSAGE_TOKEN) @@ -333,7 +333,7 @@ def _unary_request(rpc_event, state, request_deserializer): if state.client is _CANCELLED or state.statused: return None else: - start_batch_result = rpc_event.operation_call.start_batch( + start_server_batch_result = rpc_event.operation_call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), _receive_message( @@ -417,7 +417,7 @@ def _send_response(rpc_event, state, serialized_response): cygrpc.operation_send_message(serialized_response, _EMPTY_FLAGS), ) token = _SEND_MESSAGE_TOKEN - rpc_event.operation_call.start_batch( + rpc_event.operation_call.start_server_batch( cygrpc.Operations(operations), _send_message(state, token)) state.due.add(token) while True: @@ -443,7 +443,7 @@ def _status(rpc_event, state, serialized_response): if serialized_response is not None: operations.append(cygrpc.operation_send_message( serialized_response, _EMPTY_FLAGS)) - rpc_event.operation_call.start_batch( + rpc_event.operation_call.start_server_batch( cygrpc.Operations(operations), _send_status_from_server(state, _SEND_STATUS_FROM_SERVER_TOKEN)) state.statused = True @@ -550,7 +550,7 @@ def _handle_unrecognized_method(rpc_event): b'Method not found!', _EMPTY_FLAGS), ) rpc_state = _RPCState() - rpc_event.operation_call.start_batch( + rpc_event.operation_call.start_server_batch( operations, lambda ignored_event: (rpc_state, (),)) return rpc_state @@ -558,7 +558,7 @@ def _handle_unrecognized_method(rpc_event): def _handle_with_method_handler(rpc_event, method_handler, thread_pool): state = _RPCState() with state.condition: - rpc_event.operation_call.start_batch( + rpc_event.operation_call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), _receive_close_on_server(state)) @@ -731,7 +731,7 @@ def _start(state): class Server(grpc.Server): - def __init__(self, generic_handlers, thread_pool): + def __init__(self, thread_pool, generic_handlers): completion_queue = cygrpc.CompletionQueue() server = cygrpc.Server() server.register_completion_queue(completion_queue) diff --git a/src/python/grpcio/grpc/beta/_client_adaptations.py b/src/python/grpcio/grpc/beta/_client_adaptations.py index 56456cc117..e4ee44d7a3 100644 --- a/src/python/grpcio/grpc/beta/_client_adaptations.py +++ b/src/python/grpcio/grpc/beta/_client_adaptations.py @@ -67,7 +67,7 @@ def _abortion(rpc_error_call): error_kind = face.Abortion.Kind.LOCAL_FAILURE if pair is None else pair[0] return face.Abortion( error_kind, rpc_error_call.initial_metadata(), - rpc_error_call.trailing_metadata(), code, rpc_error_code.details()) + rpc_error_call.trailing_metadata(), code, rpc_error_call.details()) def _abortion_error(rpc_error_call): @@ -117,7 +117,10 @@ class _Rendezvous(future.Future, face.Call): def exception(self, timeout=None): try: rpc_error_call = self._future.exception(timeout=timeout) - return _abortion_error(rpc_error_call) + if rpc_error_call is None: + return None + else: + return _abortion_error(rpc_error_call) except grpc.FutureTimeoutError: raise future.TimeoutError() except grpc.FutureCancelledError: @@ -156,9 +159,11 @@ class _Rendezvous(future.Future, face.Call): return self._call.time_remaining() def add_abortion_callback(self, abortion_callback): - registered = self._call.add_callback( - lambda: abortion_callback(_abortion(self._call))) - return None if registered else _abortion(self._call) + def done_callback(): + if self.code() is not grpc.StatusCode.OK: + abortion_callback(_abortion(self._call)) + registered = self._call.add_callback(done_callback) + return None if registered else done_callback() def protocol_context(self): return _InvocationProtocolContext() diff --git a/src/python/grpcio/grpc/beta/_server.py b/src/python/grpcio/grpc/beta/_server.py deleted file mode 100644 index eb0aadb42f..0000000000 --- a/src/python/grpcio/grpc/beta/_server.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Beta API server implementation.""" - -import threading - -from grpc._links import service -from grpc.beta import interfaces -from grpc.framework.core import implementations as _core_implementations -from grpc.framework.crust import implementations as _crust_implementations -from grpc.framework.foundation import logging_pool -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.links import utilities - -_DEFAULT_POOL_SIZE = 8 -_DEFAULT_TIMEOUT = 300 -_MAXIMUM_TIMEOUT = 24 * 60 * 60 - - -def _set_event(): - event = threading.Event() - event.set() - return event - - -class _GRPCServicer(base.Servicer): - - def __init__(self, delegate): - self._delegate = delegate - - def service(self, group, method, context, output_operator): - try: - return self._delegate.service(group, method, context, output_operator) - except base.NoSuchMethodError as e: - if e.code is None and e.details is None: - raise base.NoSuchMethodError( - interfaces.StatusCode.UNIMPLEMENTED, - 'Method "%s" of service "%s" not implemented!' % (method, group)) - else: - raise - - -class _Server(interfaces.Server): - - def __init__( - self, implementations, multi_implementation, pool, pool_size, - default_timeout, maximum_timeout, grpc_link): - self._lock = threading.Lock() - self._implementations = implementations - self._multi_implementation = multi_implementation - self._customer_pool = pool - self._pool_size = pool_size - self._default_timeout = default_timeout - self._maximum_timeout = maximum_timeout - self._grpc_link = grpc_link - - self._end_link = None - self._stop_events = None - self._pool = None - - def _start(self): - with self._lock: - if self._end_link is not None: - raise ValueError('Cannot start already-started server!') - - if self._customer_pool is None: - self._pool = logging_pool.pool(self._pool_size) - assembly_pool = self._pool - else: - assembly_pool = self._customer_pool - - servicer = _GRPCServicer( - _crust_implementations.servicer( - self._implementations, self._multi_implementation, assembly_pool)) - - self._end_link = _core_implementations.service_end_link( - servicer, self._default_timeout, self._maximum_timeout) - - self._grpc_link.join_link(self._end_link) - self._end_link.join_link(self._grpc_link) - self._grpc_link.start() - self._end_link.start() - - def _dissociate_links_and_shut_down_pool(self): - self._grpc_link.end_stop() - self._grpc_link.join_link(utilities.NULL_LINK) - self._end_link.join_link(utilities.NULL_LINK) - self._end_link = None - if self._pool is not None: - self._pool.shutdown(wait=True) - self._pool = None - - def _stop_stopping(self): - self._dissociate_links_and_shut_down_pool() - for stop_event in self._stop_events: - stop_event.set() - self._stop_events = None - - def _stop_started(self): - self._grpc_link.begin_stop() - self._end_link.stop(0).wait() - self._dissociate_links_and_shut_down_pool() - - def _foreign_thread_stop(self, end_stop_event, stop_events): - end_stop_event.wait() - with self._lock: - if self._stop_events is stop_events: - self._stop_stopping() - - def _schedule_stop(self, grace): - with self._lock: - if self._end_link is None: - return _set_event() - server_stop_event = threading.Event() - if self._stop_events is None: - self._stop_events = [server_stop_event] - self._grpc_link.begin_stop() - else: - self._stop_events.append(server_stop_event) - end_stop_event = self._end_link.stop(grace) - end_stop_thread = threading.Thread( - target=self._foreign_thread_stop, - args=(end_stop_event, self._stop_events)) - end_stop_thread.start() - return server_stop_event - - def _stop_now(self): - with self._lock: - if self._end_link is not None: - if self._stop_events is None: - self._stop_started() - else: - self._stop_stopping() - - def add_insecure_port(self, address): - with self._lock: - if self._end_link is None: - return self._grpc_link.add_port(address, None) - else: - raise ValueError('Can\'t add port to serving server!') - - def add_secure_port(self, address, server_credentials): - with self._lock: - if self._end_link is None: - return self._grpc_link.add_port( - address, server_credentials._low_credentials) # pylint: disable=protected-access - else: - raise ValueError('Can\'t add port to serving server!') - - def start(self): - self._start() - - def stop(self, grace): - if 0 < grace: - return self._schedule_stop(grace) - else: - self._stop_now() - return _set_event() - - def __enter__(self): - self._start() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self._stop_now() - return False - - def __del__(self): - self._stop_now() - - -def server( - implementations, multi_implementation, request_deserializers, - response_serializers, thread_pool, thread_pool_size, default_timeout, - maximum_timeout): - grpc_link = service.service_link(request_deserializers, response_serializers) - return _Server( - implementations, multi_implementation, thread_pool, - _DEFAULT_POOL_SIZE if thread_pool_size is None else thread_pool_size, - _DEFAULT_TIMEOUT if default_timeout is None else default_timeout, - _MAXIMUM_TIMEOUT if maximum_timeout is None else maximum_timeout, - grpc_link) diff --git a/src/python/grpcio/grpc/beta/_server_adaptations.py b/src/python/grpcio/grpc/beta/_server_adaptations.py index 1e1f80156a..cca4a1797a 100644 --- a/src/python/grpcio/grpc/beta/_server_adaptations.py +++ b/src/python/grpcio/grpc/beta/_server_adaptations.py @@ -371,4 +371,5 @@ def server( _DEFAULT_POOL_SIZE if thread_pool_size is None else thread_pool_size) else: effective_thread_pool = thread_pool - return _Server(grpc.server((generic_rpc_handler,), effective_thread_pool)) + return _Server( + grpc.server(effective_thread_pool, handlers=(generic_rpc_handler,))) diff --git a/src/python/grpcio/grpc/beta/_stub.py b/src/python/grpcio/grpc/beta/_stub.py deleted file mode 100644 index 2af019309a..0000000000 --- a/src/python/grpcio/grpc/beta/_stub.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Beta API stub implementation.""" - -import threading - -from grpc._links import invocation -from grpc.framework.core import implementations as _core_implementations -from grpc.framework.crust import implementations as _crust_implementations -from grpc.framework.foundation import logging_pool -from grpc.framework.interfaces.links import utilities - -_DEFAULT_POOL_SIZE = 6 - - -class _AutoIntermediary(object): - - def __init__(self, up, down, delegate): - self._lock = threading.Lock() - self._up = up - self._down = down - self._in_context = False - self._delegate = delegate - - def __getattr__(self, attr): - with self._lock: - if self._delegate is None: - raise AttributeError('No useful attributes out of context!') - else: - return getattr(self._delegate, attr) - - def __enter__(self): - with self._lock: - if self._in_context: - raise ValueError('Already in context!') - elif self._delegate is None: - self._delegate = self._up() - self._in_context = True - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - with self._lock: - if not self._in_context: - raise ValueError('Not in context!') - self._down() - self._in_context = False - self._delegate = None - return False - - def __del__(self): - with self._lock: - if self._delegate is not None: - self._down() - self._delegate = None - - -class _StubAssemblyManager(object): - - def __init__( - self, thread_pool, thread_pool_size, end_link, grpc_link, stub_creator): - self._thread_pool = thread_pool - self._pool_size = thread_pool_size - self._end_link = end_link - self._grpc_link = grpc_link - self._stub_creator = stub_creator - self._own_pool = None - - def up(self): - if self._thread_pool is None: - self._own_pool = logging_pool.pool( - _DEFAULT_POOL_SIZE if self._pool_size is None else self._pool_size) - assembly_pool = self._own_pool - else: - assembly_pool = self._thread_pool - self._end_link.join_link(self._grpc_link) - self._grpc_link.join_link(self._end_link) - self._end_link.start() - self._grpc_link.start() - return self._stub_creator(self._end_link, assembly_pool) - - def down(self): - self._end_link.stop(0).wait() - self._grpc_link.stop() - self._end_link.join_link(utilities.NULL_LINK) - self._grpc_link.join_link(utilities.NULL_LINK) - if self._own_pool is not None: - self._own_pool.shutdown(wait=True) - self._own_pool = None - - -def _assemble( - channel, host, metadata_transformer, request_serializers, - response_deserializers, thread_pool, thread_pool_size, stub_creator): - end_link = _core_implementations.invocation_end_link() - grpc_link = invocation.invocation_link( - channel, host, metadata_transformer, request_serializers, - response_deserializers) - stub_assembly_manager = _StubAssemblyManager( - thread_pool, thread_pool_size, end_link, grpc_link, stub_creator) - stub = stub_assembly_manager.up() - return _AutoIntermediary( - stub_assembly_manager.up, stub_assembly_manager.down, stub) - - -def _dynamic_stub_creator(service, cardinalities): - def create_dynamic_stub(end_link, invocation_pool): - return _crust_implementations.dynamic_stub( - end_link, service, cardinalities, invocation_pool) - return create_dynamic_stub - - -def generic_stub( - channel, host, metadata_transformer, request_serializers, - response_deserializers, thread_pool, thread_pool_size): - return _assemble( - channel, host, metadata_transformer, request_serializers, - response_deserializers, thread_pool, thread_pool_size, - _crust_implementations.generic_stub) - - -def dynamic_stub( - channel, host, service, cardinalities, metadata_transformer, - request_serializers, response_deserializers, thread_pool, - thread_pool_size): - return _assemble( - channel, host, metadata_transformer, request_serializers, - response_deserializers, thread_pool, thread_pool_size, - _dynamic_stub_creator(service, cardinalities)) diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py index 4ae6e7d675..ab25fd5eec 100644 --- a/src/python/grpcio/grpc/beta/implementations.py +++ b/src/python/grpcio/grpc/beta/implementations.py @@ -37,7 +37,6 @@ import threading # pylint: disable=unused-import # cardinality and face are referenced from specification in this module. import grpc from grpc import _auth -from grpc._adapter import _types from grpc.beta import _client_adaptations from grpc.beta import _server_adaptations from grpc.beta import interfaces diff --git a/src/python/grpcio/grpc/framework/core/__init__.py b/src/python/grpcio/grpc/framework/core/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio/grpc/framework/core/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio/grpc/framework/core/_constants.py b/src/python/grpcio/grpc/framework/core/_constants.py deleted file mode 100644 index 0f47cb48e0..0000000000 --- a/src/python/grpcio/grpc/framework/core/_constants.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Private constants for the package.""" - -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.links import links - -TICKET_SUBSCRIPTION_FOR_BASE_SUBSCRIPTION_KIND = { - base.Subscription.Kind.NONE: links.Ticket.Subscription.NONE, - base.Subscription.Kind.TERMINATION_ONLY: - links.Ticket.Subscription.TERMINATION, - base.Subscription.Kind.FULL: links.Ticket.Subscription.FULL, - } - -# Mapping from abortive operation outcome to ticket termination to be -# sent to the other side of the operation, or None to indicate that no -# ticket should be sent to the other side in the event of such an -# outcome. -ABORTION_OUTCOME_TO_TICKET_TERMINATION = { - base.Outcome.Kind.CANCELLED: links.Ticket.Termination.CANCELLATION, - base.Outcome.Kind.EXPIRED: links.Ticket.Termination.EXPIRATION, - base.Outcome.Kind.LOCAL_SHUTDOWN: links.Ticket.Termination.SHUTDOWN, - base.Outcome.Kind.REMOTE_SHUTDOWN: None, - base.Outcome.Kind.RECEPTION_FAILURE: - links.Ticket.Termination.RECEPTION_FAILURE, - base.Outcome.Kind.TRANSMISSION_FAILURE: None, - base.Outcome.Kind.LOCAL_FAILURE: links.Ticket.Termination.LOCAL_FAILURE, - base.Outcome.Kind.REMOTE_FAILURE: links.Ticket.Termination.REMOTE_FAILURE, -} - -INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Core) internal error! )-:' -TERMINATION_CALLBACK_EXCEPTION_LOG_MESSAGE = ( - 'Exception calling termination callback!') diff --git a/src/python/grpcio/grpc/framework/core/_context.py b/src/python/grpcio/grpc/framework/core/_context.py deleted file mode 100644 index a346e9d478..0000000000 --- a/src/python/grpcio/grpc/framework/core/_context.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for operation context.""" - -import time - -# _interfaces is referenced from specification in this module. -from grpc.framework.core import _interfaces # pylint: disable=unused-import -from grpc.framework.core import _utilities -from grpc.framework.interfaces.base import base - - -class OperationContext(base.OperationContext): - """An implementation of interfaces.OperationContext.""" - - def __init__( - self, lock, termination_manager, transmission_manager, - expiration_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - """ - self._lock = lock - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._expiration_manager = expiration_manager - - def _abort(self, outcome_kind): - with self._lock: - if self._termination_manager.outcome is None: - outcome = _utilities.Outcome(outcome_kind, None, None) - self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome) - self._expiration_manager.terminate() - - def outcome(self): - """See base.OperationContext.outcome for specification.""" - with self._lock: - return self._termination_manager.outcome - - def add_termination_callback(self, callback): - """See base.OperationContext.add_termination_callback.""" - with self._lock: - if self._termination_manager.outcome is None: - self._termination_manager.add_callback(callback) - return None - else: - return self._termination_manager.outcome - - def time_remaining(self): - """See base.OperationContext.time_remaining for specification.""" - with self._lock: - deadline = self._expiration_manager.deadline() - return max(0.0, deadline - time.time()) - - def cancel(self): - """See base.OperationContext.cancel for specification.""" - self._abort(base.Outcome.Kind.CANCELLED) - - def fail(self, exception): - """See base.OperationContext.fail for specification.""" - self._abort(base.Outcome.Kind.LOCAL_FAILURE) diff --git a/src/python/grpcio/grpc/framework/core/_emission.py b/src/python/grpcio/grpc/framework/core/_emission.py deleted file mode 100644 index 8ab59dc3e5..0000000000 --- a/src/python/grpcio/grpc/framework/core/_emission.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for handling emitted values.""" - -from grpc.framework.core import _interfaces -from grpc.framework.core import _utilities -from grpc.framework.interfaces.base import base - - -class EmissionManager(_interfaces.EmissionManager): - """An EmissionManager implementation.""" - - def __init__( - self, lock, termination_manager, transmission_manager, - expiration_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - """ - self._lock = lock - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._expiration_manager = expiration_manager - self._ingestion_manager = None - - self._initial_metadata_seen = False - self._payload_seen = False - self._completion_seen = False - - def set_ingestion_manager(self, ingestion_manager): - """Sets the ingestion manager with which this manager will cooperate. - - Args: - ingestion_manager: The _interfaces.IngestionManager for the operation. - """ - self._ingestion_manager = ingestion_manager - - def advance( - self, initial_metadata=None, payload=None, completion=None, - allowance=None): - initial_metadata_present = initial_metadata is not None - payload_present = payload is not None - completion_present = completion is not None - allowance_present = allowance is not None - with self._lock: - if self._termination_manager.outcome is None: - if (initial_metadata_present and ( - self._initial_metadata_seen or self._payload_seen or - self._completion_seen) or - payload_present and self._completion_seen or - completion_present and self._completion_seen or - allowance_present and allowance <= 0): - outcome = _utilities.Outcome( - base.Outcome.Kind.LOCAL_FAILURE, None, None) - self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome) - self._expiration_manager.terminate() - else: - self._initial_metadata_seen |= initial_metadata_present - self._payload_seen |= payload_present - self._completion_seen |= completion_present - if completion_present: - self._termination_manager.emission_complete() - self._ingestion_manager.local_emissions_done() - self._transmission_manager.advance( - initial_metadata, payload, completion, allowance) - if allowance_present: - self._ingestion_manager.add_local_allowance(allowance) diff --git a/src/python/grpcio/grpc/framework/core/_end.py b/src/python/grpcio/grpc/framework/core/_end.py deleted file mode 100644 index 009d27c915..0000000000 --- a/src/python/grpcio/grpc/framework/core/_end.py +++ /dev/null @@ -1,244 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Implementation of base.End.""" - -import abc -import threading -import uuid - -import six - -from grpc.framework.core import _operation -from grpc.framework.core import _utilities -from grpc.framework.foundation import callable_util -from grpc.framework.foundation import later -from grpc.framework.foundation import logging_pool -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.links import links -from grpc.framework.interfaces.links import utilities - -_IDLE_ACTION_EXCEPTION_LOG_MESSAGE = 'Exception calling idle action!' - - -class End(six.with_metaclass(abc.ABCMeta, base.End, links.Link)): - """A bridge between base.End and links.Link. - - Implementations of this interface translate arriving tickets into - calls on application objects implementing base interfaces and - translate calls from application objects implementing base interfaces - into tickets sent to a joined link. - """ - - -class _Cycle(object): - """State for a single start-stop End lifecycle.""" - - def __init__(self, pool): - self.pool = pool - self.grace = False - self.futures = [] - self.operations = {} - self.idle_actions = [] - - -def _abort(operations): - for operation in operations: - operation.abort(base.Outcome.Kind.LOCAL_SHUTDOWN) - - -def _cancel_futures(futures): - for future in futures: - future.cancel() - - -def _future_shutdown(lock, cycle, event): - def in_future(): - with lock: - _abort(cycle.operations.values()) - _cancel_futures(cycle.futures) - return in_future - - -class _End(End): - """An End implementation.""" - - def __init__(self, servicer_package): - """Constructor. - - Args: - servicer_package: A _ServicerPackage for servicing operations or None if - this end will not be used to service operations. - """ - self._lock = threading.Condition() - self._servicer_package = servicer_package - - self._stats = {outcome_kind: 0 for outcome_kind in base.Outcome.Kind} - - self._mate = None - - self._cycle = None - - def _termination_action(self, operation_id): - """Constructs the termination action for a single operation. - - Args: - operation_id: The operation ID for the termination action. - - Returns: - A callable that takes an operation outcome kind as its sole parameter and - that should be used as the termination action for the operation - associated with the given operation ID. - """ - def termination_action(outcome_kind): - with self._lock: - self._stats[outcome_kind] += 1 - self._cycle.operations.pop(operation_id, None) - if not self._cycle.operations: - for action in self._cycle.idle_actions: - self._cycle.pool.submit(action) - self._cycle.idle_actions = [] - if self._cycle.grace: - _cancel_futures(self._cycle.futures) - self._cycle.pool.shutdown(wait=False) - self._cycle = None - return termination_action - - def start(self): - """See base.End.start for specification.""" - with self._lock: - if self._cycle is not None: - raise ValueError('Tried to start a not-stopped End!') - else: - self._cycle = _Cycle(logging_pool.pool(1)) - - def stop(self, grace): - """See base.End.stop for specification.""" - with self._lock: - if self._cycle is None: - event = threading.Event() - event.set() - return event - elif not self._cycle.operations: - event = threading.Event() - self._cycle.pool.submit(event.set) - self._cycle.pool.shutdown(wait=False) - self._cycle = None - return event - else: - self._cycle.grace = True - event = threading.Event() - self._cycle.idle_actions.append(event.set) - if 0 < grace: - future = later.later( - grace, _future_shutdown(self._lock, self._cycle, event)) - self._cycle.futures.append(future) - else: - _abort(self._cycle.operations.values()) - return event - - def operate( - self, group, method, subscription, timeout, initial_metadata=None, - payload=None, completion=None, protocol_options=None): - """See base.End.operate for specification.""" - operation_id = uuid.uuid4() - with self._lock: - if self._cycle is None or self._cycle.grace: - raise ValueError('Can\'t operate on stopped or stopping End!') - termination_action = self._termination_action(operation_id) - operation = _operation.invocation_operate( - operation_id, group, method, subscription, timeout, protocol_options, - initial_metadata, payload, completion, self._mate.accept_ticket, - termination_action, self._cycle.pool) - self._cycle.operations[operation_id] = operation - return operation.context, operation.operator - - def operation_stats(self): - """See base.End.operation_stats for specification.""" - with self._lock: - return dict(self._stats) - - def add_idle_action(self, action): - """See base.End.add_idle_action for specification.""" - with self._lock: - if self._cycle is None: - raise ValueError('Can\'t add idle action to stopped End!') - action_with_exceptions_logged = callable_util.with_exceptions_logged( - action, _IDLE_ACTION_EXCEPTION_LOG_MESSAGE) - if self._cycle.operations: - self._cycle.idle_actions.append(action_with_exceptions_logged) - else: - self._cycle.pool.submit(action_with_exceptions_logged) - - def accept_ticket(self, ticket): - """See links.Link.accept_ticket for specification.""" - with self._lock: - if self._cycle is not None: - operation = self._cycle.operations.get(ticket.operation_id) - if operation is not None: - operation.handle_ticket(ticket) - elif self._servicer_package is not None and not self._cycle.grace: - termination_action = self._termination_action(ticket.operation_id) - operation = _operation.service_operate( - self._servicer_package, ticket, self._mate.accept_ticket, - termination_action, self._cycle.pool) - if operation is not None: - self._cycle.operations[ticket.operation_id] = operation - - def join_link(self, link): - """See links.Link.join_link for specification.""" - with self._lock: - self._mate = utilities.NULL_LINK if link is None else link - - -def serviceless_end_link(): - """Constructs an End usable only for invoking operations. - - Returns: - An End usable for translating operations into ticket exchange. - """ - return _End(None) - - -def serviceful_end_link(servicer, default_timeout, maximum_timeout): - """Constructs an End capable of servicing operations. - - Args: - servicer: An interfaces.Servicer for servicing operations. - default_timeout: A length of time in seconds to be used as the default - time alloted for a single operation. - maximum_timeout: A length of time in seconds to be used as the maximum - time alloted for a single operation. - - Returns: - An End capable of servicing the operations requested of it through ticket - exchange. - """ - return _End( - _utilities.ServicerPackage(servicer, default_timeout, maximum_timeout)) diff --git a/src/python/grpcio/grpc/framework/core/_expiration.py b/src/python/grpcio/grpc/framework/core/_expiration.py deleted file mode 100644 index ded0ab6bce..0000000000 --- a/src/python/grpcio/grpc/framework/core/_expiration.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for operation expiration.""" - -import time - -from grpc.framework.core import _interfaces -from grpc.framework.core import _utilities -from grpc.framework.foundation import later -from grpc.framework.interfaces.base import base - - -class _ExpirationManager(_interfaces.ExpirationManager): - """An implementation of _interfaces.ExpirationManager.""" - - def __init__( - self, commencement, timeout, maximum_timeout, lock, termination_manager, - transmission_manager): - """Constructor. - - Args: - commencement: The time in seconds since the epoch at which the operation - began. - timeout: A length of time in seconds to allow for the operation to run. - maximum_timeout: The maximum length of time in seconds to allow for the - operation to run despite what is requested via this object's - change_timout method. - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - """ - self._lock = lock - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._commencement = commencement - self._maximum_timeout = maximum_timeout - - self._timeout = timeout - self._deadline = commencement + timeout - self._index = None - self._future = None - - def _expire(self, index): - def expire(): - with self._lock: - if self._future is not None and index == self._index: - self._future = None - self._termination_manager.expire() - self._transmission_manager.abort( - _utilities.Outcome(base.Outcome.Kind.EXPIRED, None, None)) - return expire - - def start(self): - self._index = 0 - self._future = later.later(self._timeout, self._expire(0)) - - def change_timeout(self, timeout): - if self._future is not None and timeout != self._timeout: - self._future.cancel() - new_timeout = min(timeout, self._maximum_timeout) - new_index = self._index + 1 - self._timeout = new_timeout - self._deadline = self._commencement + new_timeout - self._index = new_index - delay = self._deadline - time.time() - self._future = later.later(delay, self._expire(new_index)) - if new_timeout != timeout: - self._transmission_manager.timeout(new_timeout) - - def deadline(self): - return self._deadline - - def terminate(self): - if self._future: - self._future.cancel() - self._future = None - self._deadline_index = None - - -def invocation_expiration_manager( - timeout, lock, termination_manager, transmission_manager): - """Creates an _interfaces.ExpirationManager appropriate for front-side use. - - Args: - timeout: A length of time in seconds to allow for the operation to run. - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - - Returns: - An _interfaces.ExpirationManager appropriate for invocation-side use. - """ - expiration_manager = _ExpirationManager( - time.time(), timeout, timeout, lock, termination_manager, - transmission_manager) - expiration_manager.start() - return expiration_manager - - -def service_expiration_manager( - timeout, default_timeout, maximum_timeout, lock, termination_manager, - transmission_manager): - """Creates an _interfaces.ExpirationManager appropriate for back-side use. - - Args: - timeout: A length of time in seconds to allow for the operation to run. May - be None in which case default_timeout will be used. - default_timeout: The default length of time in seconds to allow for the - operation to run if the front-side customer has not specified such a value - (or if the value they specified is not yet known). - maximum_timeout: The maximum length of time in seconds to allow for the - operation to run. - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - - Returns: - An _interfaces.ExpirationManager appropriate for service-side use. - """ - expiration_manager = _ExpirationManager( - time.time(), default_timeout if timeout is None else timeout, - maximum_timeout, lock, termination_manager, transmission_manager) - expiration_manager.start() - return expiration_manager diff --git a/src/python/grpcio/grpc/framework/core/_ingestion.py b/src/python/grpcio/grpc/framework/core/_ingestion.py deleted file mode 100644 index f2767c981b..0000000000 --- a/src/python/grpcio/grpc/framework/core/_ingestion.py +++ /dev/null @@ -1,439 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for ingestion during an operation.""" - -import abc -import collections -import enum - -import six - -from grpc.framework.core import _constants -from grpc.framework.core import _interfaces -from grpc.framework.core import _utilities -from grpc.framework.foundation import abandonment -from grpc.framework.foundation import callable_util -from grpc.framework.interfaces.base import base - -_CREATE_SUBSCRIPTION_EXCEPTION_LOG_MESSAGE = 'Exception initializing ingestion!' -_INGESTION_EXCEPTION_LOG_MESSAGE = 'Exception during ingestion!' - - -class _SubscriptionCreation( - collections.namedtuple( - '_SubscriptionCreation', - ('kind', 'subscription', 'code', 'details',))): - """A sum type for the outcome of ingestion initialization. - - Attributes: - kind: A Kind value coarsely indicating how subscription creation completed. - subscription: The created subscription. Only present if kind is - Kind.SUBSCRIPTION. - code: A code value to be sent to the other side of the operation along with - an indication that the operation is being aborted due to an error on the - remote side of the operation. Only present if kind is Kind.REMOTE_ERROR. - details: A details value to be sent to the other side of the operation - along with an indication that the operation is being aborted due to an - error on the remote side of the operation. Only present if kind is - Kind.REMOTE_ERROR. - """ - - @enum.unique - class Kind(enum.Enum): - SUBSCRIPTION = 'subscription' - REMOTE_ERROR = 'remote error' - ABANDONED = 'abandoned' - - -class _SubscriptionCreator(six.with_metaclass(abc.ABCMeta)): - """Common specification of subscription-creating behavior.""" - - @abc.abstractmethod - def create(self, group, method): - """Creates the base.Subscription of the local customer. - - Any exceptions raised by this method should be attributed to and treated as - defects in the customer code called by this method. - - Args: - group: The group identifier of the operation. - method: The method identifier of the operation. - - Returns: - A _SubscriptionCreation describing the result of subscription creation. - """ - raise NotImplementedError() - - -class _ServiceSubscriptionCreator(_SubscriptionCreator): - """A _SubscriptionCreator appropriate for service-side use.""" - - def __init__(self, servicer, operation_context, output_operator): - """Constructor. - - Args: - servicer: The base.Servicer that will service the operation. - operation_context: A base.OperationContext for the operation to be passed - to the customer. - output_operator: A base.Operator for the operation to be passed to the - customer and to be called by the customer to accept operation data - emitted by the customer. - """ - self._servicer = servicer - self._operation_context = operation_context - self._output_operator = output_operator - - def create(self, group, method): - try: - subscription = self._servicer.service( - group, method, self._operation_context, self._output_operator) - except base.NoSuchMethodError as e: - return _SubscriptionCreation( - _SubscriptionCreation.Kind.REMOTE_ERROR, None, e.code, e.details) - except abandonment.Abandoned: - return _SubscriptionCreation( - _SubscriptionCreation.Kind.ABANDONED, None, None, None) - else: - return _SubscriptionCreation( - _SubscriptionCreation.Kind.SUBSCRIPTION, subscription, None, None) - - -def _wrap(behavior): - def wrapped(*args, **kwargs): - try: - behavior(*args, **kwargs) - except abandonment.Abandoned: - return False - else: - return True - return wrapped - - -class _IngestionManager(_interfaces.IngestionManager): - """An implementation of _interfaces.IngestionManager.""" - - def __init__( - self, lock, pool, subscription, subscription_creator, termination_manager, - transmission_manager, expiration_manager, protocol_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - pool: A thread pool in which to execute customer code. - subscription: A base.Subscription describing the customer's interest in - operation values from the other side. May be None if - subscription_creator is not None. - subscription_creator: A _SubscriptionCreator wrapping the portion of - customer code that when called returns the base.Subscription describing - the customer's interest in operation values from the other side. May be - None if subscription is not None. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - protocol_manager: The _interfaces.ProtocolManager for the operation. - """ - self._lock = lock - self._pool = pool - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._expiration_manager = expiration_manager - self._protocol_manager = protocol_manager - - if subscription is None: - self._subscription_creator = subscription_creator - self._wrapped_operator = None - elif subscription.kind is base.Subscription.Kind.FULL: - self._subscription_creator = None - self._wrapped_operator = _wrap(subscription.operator.advance) - else: - # TODO(nathaniel): Support other subscriptions. - raise ValueError('Unsupported subscription "%s"!' % subscription.kind) - self._pending_initial_metadata = None - self._pending_payloads = [] - self._pending_completion = None - self._local_allowance = 1 - # A nonnegative integer or None, with None indicating that the local - # customer is done emitting anyway so there's no need to bother it by - # informing it that the remote customer has granted it further permission to - # emit. - self._remote_allowance = 0 - self._processing = False - - def _abort_internal_only(self): - self._subscription_creator = None - self._wrapped_operator = None - self._pending_initial_metadata = None - self._pending_payloads = None - self._pending_completion = None - - def _abort_and_notify(self, outcome_kind, code, details): - self._abort_internal_only() - if self._termination_manager.outcome is None: - outcome = _utilities.Outcome(outcome_kind, code, details) - self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome) - self._expiration_manager.terminate() - - def _operator_next(self): - """Computes the next step for full-subscription ingestion. - - Returns: - An initial_metadata, payload, completion, allowance, continue quintet - indicating what operation values (if any) are available to pass into - customer code and whether or not there is anything immediately - actionable to call customer code to do. - """ - if self._wrapped_operator is None: - return None, None, None, None, False - else: - initial_metadata, payload, completion, allowance, action = [None] * 5 - if self._pending_initial_metadata is not None: - initial_metadata = self._pending_initial_metadata - self._pending_initial_metadata = None - action = True - if self._pending_payloads and 0 < self._local_allowance: - payload = self._pending_payloads.pop(0) - self._local_allowance -= 1 - action = True - if not self._pending_payloads and self._pending_completion is not None: - completion = self._pending_completion - self._pending_completion = None - action = True - if self._remote_allowance is not None and 0 < self._remote_allowance: - allowance = self._remote_allowance - self._remote_allowance = 0 - action = True - return initial_metadata, payload, completion, allowance, bool(action) - - def _operator_process( - self, wrapped_operator, initial_metadata, payload, - completion, allowance): - while True: - advance_outcome = callable_util.call_logging_exceptions( - wrapped_operator, _INGESTION_EXCEPTION_LOG_MESSAGE, - initial_metadata=initial_metadata, payload=payload, - completion=completion, allowance=allowance) - if advance_outcome.exception is None: - if advance_outcome.return_value: - with self._lock: - if self._termination_manager.outcome is not None: - return - if completion is not None: - self._termination_manager.ingestion_complete() - initial_metadata, payload, completion, allowance, moar = ( - self._operator_next()) - if not moar: - self._processing = False - return - else: - with self._lock: - if self._termination_manager.outcome is None: - self._abort_and_notify( - base.Outcome.Kind.LOCAL_FAILURE, None, None) - return - else: - with self._lock: - if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) - return - - def _operator_post_create(self, subscription): - wrapped_operator = _wrap(subscription.operator.advance) - with self._lock: - if self._termination_manager.outcome is not None: - return - self._wrapped_operator = wrapped_operator - self._subscription_creator = None - metadata, payload, completion, allowance, moar = self._operator_next() - if not moar: - self._processing = False - return - self._operator_process( - wrapped_operator, metadata, payload, completion, allowance) - - def _create(self, subscription_creator, group, name): - outcome = callable_util.call_logging_exceptions( - subscription_creator.create, - _CREATE_SUBSCRIPTION_EXCEPTION_LOG_MESSAGE, group, name) - if outcome.return_value is None: - with self._lock: - if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) - elif outcome.return_value.kind is _SubscriptionCreation.Kind.ABANDONED: - with self._lock: - if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) - elif outcome.return_value.kind is _SubscriptionCreation.Kind.REMOTE_ERROR: - code = outcome.return_value.code - details = outcome.return_value.details - with self._lock: - if self._termination_manager.outcome is None: - self._abort_and_notify( - base.Outcome.Kind.REMOTE_FAILURE, code, details) - elif outcome.return_value.subscription.kind is base.Subscription.Kind.FULL: - self._protocol_manager.set_protocol_receiver( - outcome.return_value.subscription.protocol_receiver) - self._operator_post_create(outcome.return_value.subscription) - else: - # TODO(nathaniel): Support other subscriptions. - raise ValueError( - 'Unsupported "%s"!' % outcome.return_value.subscription.kind) - - def _store_advance(self, initial_metadata, payload, completion, allowance): - if initial_metadata is not None: - self._pending_initial_metadata = initial_metadata - if payload is not None: - self._pending_payloads.append(payload) - if completion is not None: - self._pending_completion = completion - if allowance is not None and self._remote_allowance is not None: - self._remote_allowance += allowance - - def _operator_advance(self, initial_metadata, payload, completion, allowance): - if self._processing: - self._store_advance(initial_metadata, payload, completion, allowance) - else: - action = False - if initial_metadata is not None: - action = True - if payload is not None: - if 0 < self._local_allowance: - self._local_allowance -= 1 - action = True - else: - self._pending_payloads.append(payload) - payload = False - if completion is not None: - if self._pending_payloads: - self._pending_completion = completion - else: - action = True - if allowance is not None and self._remote_allowance is not None: - allowance += self._remote_allowance - self._remote_allowance = 0 - action = True - if action: - self._pool.submit( - callable_util.with_exceptions_logged( - self._operator_process, _constants.INTERNAL_ERROR_LOG_MESSAGE), - self._wrapped_operator, initial_metadata, payload, completion, - allowance) - - def set_group_and_method(self, group, method): - """See _interfaces.IngestionManager.set_group_and_method for spec.""" - if self._subscription_creator is not None and not self._processing: - self._pool.submit( - callable_util.with_exceptions_logged( - self._create, _constants.INTERNAL_ERROR_LOG_MESSAGE), - self._subscription_creator, group, method) - self._processing = True - - def add_local_allowance(self, allowance): - """See _interfaces.IngestionManager.add_local_allowance for spec.""" - if any((self._subscription_creator, self._wrapped_operator,)): - self._local_allowance += allowance - if not self._processing: - initial_metadata, payload, completion, allowance, moar = ( - self._operator_next()) - if moar: - self._pool.submit( - callable_util.with_exceptions_logged( - self._operator_process, - _constants.INTERNAL_ERROR_LOG_MESSAGE), - initial_metadata, payload, completion, allowance) - - def local_emissions_done(self): - self._remote_allowance = None - - def advance(self, initial_metadata, payload, completion, allowance): - """See _interfaces.IngestionManager.advance for specification.""" - if self._subscription_creator is not None: - self._store_advance(initial_metadata, payload, completion, allowance) - elif self._wrapped_operator is not None: - self._operator_advance(initial_metadata, payload, completion, allowance) - - -def invocation_ingestion_manager( - subscription, lock, pool, termination_manager, transmission_manager, - expiration_manager, protocol_manager): - """Creates an IngestionManager appropriate for invocation-side use. - - Args: - subscription: A base.Subscription indicating the customer's interest in the - data and results from the service-side of the operation. - lock: The operation-wide lock. - pool: A thread pool in which to execute customer code. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - protocol_manager: The _interfaces.ProtocolManager for the operation. - - Returns: - An IngestionManager appropriate for invocation-side use. - """ - return _IngestionManager( - lock, pool, subscription, None, termination_manager, transmission_manager, - expiration_manager, protocol_manager) - - -def service_ingestion_manager( - servicer, operation_context, output_operator, lock, pool, - termination_manager, transmission_manager, expiration_manager, - protocol_manager): - """Creates an IngestionManager appropriate for service-side use. - - The returned IngestionManager will require its set_group_and_name method to be - called before its advance method may be called. - - Args: - servicer: A base.Servicer for servicing the operation. - operation_context: A base.OperationContext for the operation to be passed to - the customer. - output_operator: A base.Operator for the operation to be passed to the - customer and to be called by the customer to accept operation data output - by the customer. - lock: The operation-wide lock. - pool: A thread pool in which to execute customer code. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - protocol_manager: The _interfaces.ProtocolManager for the operation. - - Returns: - An IngestionManager appropriate for service-side use. - """ - subscription_creator = _ServiceSubscriptionCreator( - servicer, operation_context, output_operator) - return _IngestionManager( - lock, pool, None, subscription_creator, termination_manager, - transmission_manager, expiration_manager, protocol_manager) diff --git a/src/python/grpcio/grpc/framework/core/_interfaces.py b/src/python/grpcio/grpc/framework/core/_interfaces.py deleted file mode 100644 index 63ac82f80e..0000000000 --- a/src/python/grpcio/grpc/framework/core/_interfaces.py +++ /dev/null @@ -1,331 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Package-internal interfaces.""" - -import abc - -import six - -from grpc.framework.interfaces.base import base - - -class TerminationManager(six.with_metaclass(abc.ABCMeta)): - """An object responsible for handling the termination of an operation. - - Attributes: - outcome: None if the operation is active or a base.Outcome value if it has - terminated. - """ - - @abc.abstractmethod - def add_callback(self, callback): - """Registers a callback to be called on operation termination. - - If the operation has already terminated the callback will not be called. - - Args: - callback: A callable that will be passed a base.Outcome value. - - Returns: - None if the operation has not yet terminated and the passed callback will - be called when it does, or a base.Outcome value describing the - operation termination if the operation has terminated and the callback - will not be called as a result of this method call. - """ - raise NotImplementedError() - - @abc.abstractmethod - def emission_complete(self): - """Indicates that emissions from customer code have completed.""" - raise NotImplementedError() - - @abc.abstractmethod - def transmission_complete(self): - """Indicates that transmissions to the remote end are complete. - - Returns: - True if the operation has terminated or False if the operation remains - ongoing. - """ - raise NotImplementedError() - - @abc.abstractmethod - def reception_complete(self, code, details): - """Indicates that reception from the other side is complete. - - Args: - code: An application-specific code value. - details: An application-specific details value. - """ - raise NotImplementedError() - - @abc.abstractmethod - def ingestion_complete(self): - """Indicates that customer code ingestion of received values is complete.""" - raise NotImplementedError() - - @abc.abstractmethod - def expire(self): - """Indicates that the operation must abort because it has taken too long.""" - raise NotImplementedError() - - @abc.abstractmethod - def abort(self, outcome): - """Indicates that the operation must abort for the indicated reason. - - Args: - outcome: A base.Outcome indicating operation abortion. - """ - raise NotImplementedError() - - -class TransmissionManager(six.with_metaclass(abc.ABCMeta)): - """A manager responsible for transmitting to the other end of an operation.""" - - @abc.abstractmethod - def kick_off( - self, group, method, timeout, protocol_options, initial_metadata, - payload, completion, allowance): - """Transmits the values associated with operation invocation.""" - raise NotImplementedError() - - @abc.abstractmethod - def advance(self, initial_metadata, payload, completion, allowance): - """Accepts values for transmission to the other end of the operation. - - Args: - initial_metadata: An initial metadata value to be transmitted to the other - side of the operation. May only ever be non-None once. - payload: A payload value. - completion: A base.Completion value. May only ever be non-None in the last - transmission to be made to the other side. - allowance: A positive integer communicating the number of additional - payloads allowed to be transmitted from the other side to this side of - the operation, or None if no additional allowance is being granted in - this call. - """ - raise NotImplementedError() - - @abc.abstractmethod - def timeout(self, timeout): - """Accepts for transmission to the other side a new timeout value. - - Args: - timeout: A positive float used as the new timeout value for the operation - to be transmitted to the other side. - """ - raise NotImplementedError() - - @abc.abstractmethod - def allowance(self, allowance): - """Indicates to this manager that the remote customer is allowing payloads. - - Args: - allowance: A positive integer indicating the number of additional payloads - the remote customer is allowing to be transmitted from this side of the - operation. - """ - raise NotImplementedError() - - @abc.abstractmethod - def remote_complete(self): - """Indicates to this manager that data from the remote side is complete.""" - raise NotImplementedError() - - @abc.abstractmethod - def abort(self, outcome): - """Indicates that the operation has aborted. - - Args: - outcome: A base.Outcome for the operation. If None, indicates that the - operation abortion should not be communicated to the other side of the - operation. - """ - raise NotImplementedError() - - -class ExpirationManager(six.with_metaclass(abc.ABCMeta)): - """A manager responsible for aborting the operation if it runs out of time.""" - - @abc.abstractmethod - def change_timeout(self, timeout): - """Changes the timeout allotted for the operation. - - Operation duration is always measure from the beginning of the operation; - calling this method changes the operation's allotted time to timeout total - seconds, not timeout seconds from the time of this method call. - - Args: - timeout: A length of time in seconds to allow for the operation. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deadline(self): - """Returns the time until which the operation is allowed to run. - - Returns: - The time (seconds since the epoch) at which the operation will expire. - """ - raise NotImplementedError() - - @abc.abstractmethod - def terminate(self): - """Indicates to this manager that the operation has terminated.""" - raise NotImplementedError() - - -class ProtocolManager(six.with_metaclass(abc.ABCMeta)): - """A manager of protocol-specific values passing through an operation.""" - - @abc.abstractmethod - def set_protocol_receiver(self, protocol_receiver): - """Registers the customer object that will receive protocol objects. - - Args: - protocol_receiver: A base.ProtocolReceiver to which protocol objects for - the operation should be passed. - """ - raise NotImplementedError() - - @abc.abstractmethod - def accept_protocol_context(self, protocol_context): - """Accepts the protocol context object for the operation. - - Args: - protocol_context: An object designated for use as the protocol context - of the operation, with further semantics implementation-determined. - """ - raise NotImplementedError() - - -class EmissionManager(six.with_metaclass(abc.ABCMeta, base.Operator)): - """A manager of values emitted by customer code.""" - - @abc.abstractmethod - def advance( - self, initial_metadata=None, payload=None, completion=None, - allowance=None): - """Accepts a value emitted by customer code. - - This method should only be called by customer code. - - Args: - initial_metadata: An initial metadata value emitted by the local customer - to be sent to the other side of the operation. - payload: A payload value emitted by the local customer to be sent to the - other side of the operation. - completion: A Completion value emitted by the local customer to be sent to - the other side of the operation. - allowance: A positive integer indicating an additional number of payloads - that the local customer is willing to accept from the other side of the - operation. - """ - raise NotImplementedError() - - -class IngestionManager(six.with_metaclass(abc.ABCMeta)): - """A manager responsible for executing customer code. - - This name of this manager comes from its responsibility to pass successive - values from the other side of the operation into the code of the local - customer. - """ - - @abc.abstractmethod - def set_group_and_method(self, group, method): - """Communicates to this IngestionManager the operation group and method. - - Args: - group: The group identifier of the operation. - method: The method identifier of the operation. - """ - raise NotImplementedError() - - @abc.abstractmethod - def add_local_allowance(self, allowance): - """Communicates to this IngestionManager that more payloads may be ingested. - - Args: - allowance: A positive integer indicating an additional number of payloads - that the local customer is willing to ingest. - """ - raise NotImplementedError() - - @abc.abstractmethod - def local_emissions_done(self): - """Indicates to this manager that local emissions are done.""" - raise NotImplementedError() - - @abc.abstractmethod - def advance(self, initial_metadata, payload, completion, allowance): - """Advances the operation by passing values to the local customer.""" - raise NotImplementedError() - - -class ReceptionManager(six.with_metaclass(abc.ABCMeta)): - """A manager responsible for receiving tickets from the other end.""" - - @abc.abstractmethod - def receive_ticket(self, ticket): - """Handle a ticket from the other side of the operation. - - Args: - ticket: A links.Ticket for the operation. - """ - raise NotImplementedError() - - -class Operation(six.with_metaclass(abc.ABCMeta)): - """An ongoing operation. - - Attributes: - context: A base.OperationContext object for the operation. - operator: A base.Operator object for the operation for use by the customer - of the operation. - """ - - @abc.abstractmethod - def handle_ticket(self, ticket): - """Handle a ticket from the other side of the operation. - - Args: - ticket: A links.Ticket from the other side of the operation. - """ - raise NotImplementedError() - - @abc.abstractmethod - def abort(self, outcome_kind): - """Aborts the operation. - - Args: - outcome_kind: A base.Outcome.Kind value indicating operation abortion. - """ - raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/core/_operation.py b/src/python/grpcio/grpc/framework/core/_operation.py deleted file mode 100644 index 020c0c9ed9..0000000000 --- a/src/python/grpcio/grpc/framework/core/_operation.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Implementation of operations.""" - -import threading - -from grpc.framework.core import _context -from grpc.framework.core import _emission -from grpc.framework.core import _expiration -from grpc.framework.core import _ingestion -from grpc.framework.core import _interfaces -from grpc.framework.core import _protocol -from grpc.framework.core import _reception -from grpc.framework.core import _termination -from grpc.framework.core import _transmission -from grpc.framework.core import _utilities - - -class _EasyOperation(_interfaces.Operation): - """A trivial implementation of interfaces.Operation.""" - - def __init__( - self, lock, termination_manager, transmission_manager, expiration_manager, - context, operator, reception_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - context: A base.OperationContext for use by the customer during the - operation. - operator: A base.Operator for use by the customer during the operation. - reception_manager: The _interfaces.ReceptionManager for the operation. - """ - self._lock = lock - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._expiration_manager = expiration_manager - self._reception_manager = reception_manager - - self.context = context - self.operator = operator - - def handle_ticket(self, ticket): - with self._lock: - self._reception_manager.receive_ticket(ticket) - - def abort(self, outcome_kind): - with self._lock: - if self._termination_manager.outcome is None: - outcome = _utilities.Outcome(outcome_kind, None, None) - self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome) - self._expiration_manager.terminate() - - -def invocation_operate( - operation_id, group, method, subscription, timeout, protocol_options, - initial_metadata, payload, completion, ticket_sink, termination_action, - pool): - """Constructs objects necessary for front-side operation management. - - Args: - operation_id: An object identifying the operation. - group: The group identifier of the operation. - method: The method identifier of the operation. - subscription: A base.Subscription describing the customer's interest in the - results of the operation. - timeout: A length of time in seconds to allow for the operation. - protocol_options: A transport-specific, application-specific, and/or - protocol-specific value relating to the invocation. May be None. - initial_metadata: An initial metadata value to be sent to the other side of - the operation. May be None if the initial metadata will be passed later or - if there will be no initial metadata passed at all. - payload: The first payload value to be transmitted to the other side. May be - None if there is no such value or if the customer chose not to pass it at - operation invocation. - completion: A base.Completion value indicating the end of values passed to - the other side of the operation. - ticket_sink: A callable that accepts links.Tickets and delivers them to the - other side of the operation. - termination_action: A callable that accepts the outcome of the operation as - a base.Outcome value to be called on operation completion. - pool: A thread pool with which to do the work of the operation. - - Returns: - An _interfaces.Operation for the operation. - """ - lock = threading.Lock() - with lock: - termination_manager = _termination.invocation_termination_manager( - termination_action, pool) - transmission_manager = _transmission.TransmissionManager( - operation_id, ticket_sink, lock, pool, termination_manager) - expiration_manager = _expiration.invocation_expiration_manager( - timeout, lock, termination_manager, transmission_manager) - protocol_manager = _protocol.invocation_protocol_manager( - subscription, lock, pool, termination_manager, transmission_manager, - expiration_manager) - operation_context = _context.OperationContext( - lock, termination_manager, transmission_manager, expiration_manager) - emission_manager = _emission.EmissionManager( - lock, termination_manager, transmission_manager, expiration_manager) - ingestion_manager = _ingestion.invocation_ingestion_manager( - subscription, lock, pool, termination_manager, transmission_manager, - expiration_manager, protocol_manager) - reception_manager = _reception.ReceptionManager( - termination_manager, transmission_manager, expiration_manager, - protocol_manager, ingestion_manager) - - termination_manager.set_expiration_manager(expiration_manager) - transmission_manager.set_expiration_manager(expiration_manager) - emission_manager.set_ingestion_manager(ingestion_manager) - - transmission_manager.kick_off( - group, method, timeout, protocol_options, initial_metadata, payload, - completion, None) - - return _EasyOperation( - lock, termination_manager, transmission_manager, expiration_manager, - operation_context, emission_manager, reception_manager) - - -def service_operate( - servicer_package, ticket, ticket_sink, termination_action, pool): - """Constructs an Operation for service of an operation. - - Args: - servicer_package: A _utilities.ServicerPackage to be used servicing the - operation. - ticket: The first links.Ticket received for the operation. - ticket_sink: A callable that accepts links.Tickets and delivers them to the - other side of the operation. - termination_action: A callable that accepts the outcome of the operation as - a base.Outcome value to be called on operation completion. - pool: A thread pool with which to do the work of the operation. - - Returns: - An _interfaces.Operation for the operation. - """ - lock = threading.Lock() - with lock: - termination_manager = _termination.service_termination_manager( - termination_action, pool) - transmission_manager = _transmission.TransmissionManager( - ticket.operation_id, ticket_sink, lock, pool, termination_manager) - expiration_manager = _expiration.service_expiration_manager( - ticket.timeout, servicer_package.default_timeout, - servicer_package.maximum_timeout, lock, termination_manager, - transmission_manager) - protocol_manager = _protocol.service_protocol_manager( - lock, pool, termination_manager, transmission_manager, - expiration_manager) - operation_context = _context.OperationContext( - lock, termination_manager, transmission_manager, expiration_manager) - emission_manager = _emission.EmissionManager( - lock, termination_manager, transmission_manager, expiration_manager) - ingestion_manager = _ingestion.service_ingestion_manager( - servicer_package.servicer, operation_context, emission_manager, lock, - pool, termination_manager, transmission_manager, expiration_manager, - protocol_manager) - reception_manager = _reception.ReceptionManager( - termination_manager, transmission_manager, expiration_manager, - protocol_manager, ingestion_manager) - - termination_manager.set_expiration_manager(expiration_manager) - transmission_manager.set_expiration_manager(expiration_manager) - emission_manager.set_ingestion_manager(ingestion_manager) - - reception_manager.receive_ticket(ticket) - - return _EasyOperation( - lock, termination_manager, transmission_manager, expiration_manager, - operation_context, emission_manager, reception_manager) diff --git a/src/python/grpcio/grpc/framework/core/_protocol.py b/src/python/grpcio/grpc/framework/core/_protocol.py deleted file mode 100644 index 3177b5e302..0000000000 --- a/src/python/grpcio/grpc/framework/core/_protocol.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for passing protocol objects in an operation.""" - -import collections -import enum - -from grpc.framework.core import _constants -from grpc.framework.core import _interfaces -from grpc.framework.core import _utilities -from grpc.framework.foundation import callable_util -from grpc.framework.interfaces.base import base - -_EXCEPTION_LOG_MESSAGE = 'Exception delivering protocol object!' - -_LOCAL_FAILURE_OUTCOME = _utilities.Outcome( - base.Outcome.Kind.LOCAL_FAILURE, None, None) - - -class _Awaited( - collections.namedtuple('_Awaited', ('kind', 'value',))): - - @enum.unique - class Kind(enum.Enum): - NOT_YET_ARRIVED = 'not yet arrived' - ARRIVED = 'arrived' - -_NOT_YET_ARRIVED = _Awaited(_Awaited.Kind.NOT_YET_ARRIVED, None) -_ARRIVED_AND_NONE = _Awaited(_Awaited.Kind.ARRIVED, None) - - -class _Transitory( - collections.namedtuple('_Transitory', ('kind', 'value',))): - - @enum.unique - class Kind(enum.Enum): - NOT_YET_SEEN = 'not yet seen' - PRESENT = 'present' - GONE = 'gone' - -_NOT_YET_SEEN = _Transitory(_Transitory.Kind.NOT_YET_SEEN, None) -_GONE = _Transitory(_Transitory.Kind.GONE, None) - - -class _ProtocolManager(_interfaces.ProtocolManager): - """An implementation of _interfaces.ExpirationManager.""" - - def __init__( - self, protocol_receiver, lock, pool, termination_manager, - transmission_manager, expiration_manager): - """Constructor. - - Args: - protocol_receiver: An _Awaited wrapping of the base.ProtocolReceiver to - which protocol objects should be passed during the operation. May be - of kind _Awaited.Kind.NOT_YET_ARRIVED if the customer's subscription is - not yet known and may be of kind _Awaited.Kind.ARRIVED but with a value - of None if the customer's subscription did not include a - ProtocolReceiver. - lock: The operation-wide lock. - pool: A thread pool. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - """ - self._lock = lock - self._pool = pool - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._expiration_manager = expiration_manager - - self._protocol_receiver = protocol_receiver - self._context = _NOT_YET_SEEN - - def _abort_and_notify(self, outcome): - if self._termination_manager.outcome is None: - self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome) - self._expiration_manager.terminate() - - def _deliver(self, behavior, value): - def deliver(): - delivery_outcome = callable_util.call_logging_exceptions( - behavior, _EXCEPTION_LOG_MESSAGE, value) - if delivery_outcome.kind is callable_util.Outcome.Kind.RAISED: - with self._lock: - self._abort_and_notify(_LOCAL_FAILURE_OUTCOME) - self._pool.submit( - callable_util.with_exceptions_logged( - deliver, _constants.INTERNAL_ERROR_LOG_MESSAGE)) - - def set_protocol_receiver(self, protocol_receiver): - """See _interfaces.ProtocolManager.set_protocol_receiver for spec.""" - self._protocol_receiver = _Awaited(_Awaited.Kind.ARRIVED, protocol_receiver) - if (self._context.kind is _Transitory.Kind.PRESENT and - protocol_receiver is not None): - self._deliver(protocol_receiver.context, self._context.value) - self._context = _GONE - - def accept_protocol_context(self, protocol_context): - """See _interfaces.ProtocolManager.accept_protocol_context for spec.""" - if self._protocol_receiver.kind is _Awaited.Kind.ARRIVED: - if self._protocol_receiver.value is not None: - self._deliver(self._protocol_receiver.value.context, protocol_context) - self._context = _GONE - else: - self._context = _Transitory(_Transitory.Kind.PRESENT, protocol_context) - - -def invocation_protocol_manager( - subscription, lock, pool, termination_manager, transmission_manager, - expiration_manager): - """Creates an _interfaces.ProtocolManager for invocation-side use. - - Args: - subscription: The local customer's subscription to the operation. - lock: The operation-wide lock. - pool: A thread pool. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - """ - if subscription.kind is base.Subscription.Kind.FULL: - awaited_protocol_receiver = _Awaited( - _Awaited.Kind.ARRIVED, subscription.protocol_receiver) - else: - awaited_protocol_receiver = _ARRIVED_AND_NONE - return _ProtocolManager( - awaited_protocol_receiver, lock, pool, termination_manager, - transmission_manager, expiration_manager) - - -def service_protocol_manager( - lock, pool, termination_manager, transmission_manager, expiration_manager): - """Creates an _interfaces.ProtocolManager for service-side use. - - Args: - lock: The operation-wide lock. - pool: A thread pool. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - """ - return _ProtocolManager( - _NOT_YET_ARRIVED, lock, pool, termination_manager, transmission_manager, - expiration_manager) diff --git a/src/python/grpcio/grpc/framework/core/_reception.py b/src/python/grpcio/grpc/framework/core/_reception.py deleted file mode 100644 index ff81450dee..0000000000 --- a/src/python/grpcio/grpc/framework/core/_reception.py +++ /dev/null @@ -1,159 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for ticket reception.""" - -from grpc.framework.core import _interfaces -from grpc.framework.core import _utilities -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.base import utilities -from grpc.framework.interfaces.links import links - -_REMOTE_TICKET_TERMINATION_TO_LOCAL_OUTCOME_KIND = { - links.Ticket.Termination.CANCELLATION: base.Outcome.Kind.CANCELLED, - links.Ticket.Termination.EXPIRATION: base.Outcome.Kind.EXPIRED, - links.Ticket.Termination.SHUTDOWN: base.Outcome.Kind.REMOTE_SHUTDOWN, - links.Ticket.Termination.RECEPTION_FAILURE: - base.Outcome.Kind.RECEPTION_FAILURE, - links.Ticket.Termination.TRANSMISSION_FAILURE: - base.Outcome.Kind.TRANSMISSION_FAILURE, - links.Ticket.Termination.LOCAL_FAILURE: base.Outcome.Kind.REMOTE_FAILURE, - links.Ticket.Termination.REMOTE_FAILURE: base.Outcome.Kind.LOCAL_FAILURE, -} - -_RECEPTION_FAILURE_OUTCOME = _utilities.Outcome( - base.Outcome.Kind.RECEPTION_FAILURE, None, None) - - -def _carrying_protocol_context(ticket): - return ticket.protocol is not None and ticket.protocol.kind in ( - links.Protocol.Kind.INVOCATION_CONTEXT, - links.Protocol.Kind.SERVICER_CONTEXT,) - - -class ReceptionManager(_interfaces.ReceptionManager): - """A ReceptionManager based around a _Receiver passed to it.""" - - def __init__( - self, termination_manager, transmission_manager, expiration_manager, - protocol_manager, ingestion_manager): - """Constructor. - - Args: - termination_manager: The operation's _interfaces.TerminationManager. - transmission_manager: The operation's _interfaces.TransmissionManager. - expiration_manager: The operation's _interfaces.ExpirationManager. - protocol_manager: The operation's _interfaces.ProtocolManager. - ingestion_manager: The operation's _interfaces.IngestionManager. - """ - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._expiration_manager = expiration_manager - self._protocol_manager = protocol_manager - self._ingestion_manager = ingestion_manager - - self._lowest_unseen_sequence_number = 0 - self._out_of_sequence_tickets = {} - self._aborted = False - - def _abort(self, outcome): - self._aborted = True - if self._termination_manager.outcome is None: - self._termination_manager.abort(outcome) - self._transmission_manager.abort(None) - self._expiration_manager.terminate() - - def _sequence_failure(self, ticket): - """Determines a just-arrived ticket's sequential legitimacy. - - Args: - ticket: A just-arrived ticket. - - Returns: - True if the ticket is sequentially legitimate; False otherwise. - """ - if ticket.sequence_number < self._lowest_unseen_sequence_number: - return True - elif ticket.sequence_number in self._out_of_sequence_tickets: - return True - else: - return False - - def _process_one(self, ticket): - if ticket.sequence_number == 0: - self._ingestion_manager.set_group_and_method(ticket.group, ticket.method) - if _carrying_protocol_context(ticket): - self._protocol_manager.accept_protocol_context(ticket.protocol.value) - else: - self._protocol_manager.accept_protocol_context(None) - if ticket.timeout is not None: - self._expiration_manager.change_timeout(ticket.timeout) - if ticket.termination is None: - completion = None - else: - completion = utilities.completion( - ticket.terminal_metadata, ticket.code, ticket.message) - self._termination_manager.reception_complete(ticket.code, ticket.message) - self._ingestion_manager.advance( - ticket.initial_metadata, ticket.payload, completion, ticket.allowance) - if ticket.allowance is not None: - self._transmission_manager.allowance(ticket.allowance) - - def _process(self, ticket): - """Process those tickets ready to be processed. - - Args: - ticket: A just-arrived ticket the sequence number of which matches this - _ReceptionManager's _lowest_unseen_sequence_number field. - """ - while True: - self._process_one(ticket) - next_ticket = self._out_of_sequence_tickets.pop( - ticket.sequence_number + 1, None) - if next_ticket is None: - self._lowest_unseen_sequence_number = ticket.sequence_number + 1 - return - else: - ticket = next_ticket - - def receive_ticket(self, ticket): - """See _interfaces.ReceptionManager.receive_ticket for specification.""" - if self._aborted: - return - elif self._sequence_failure(ticket): - self._abort(_RECEPTION_FAILURE_OUTCOME) - elif ticket.termination not in (None, links.Ticket.Termination.COMPLETION): - outcome_kind = _REMOTE_TICKET_TERMINATION_TO_LOCAL_OUTCOME_KIND[ - ticket.termination] - self._abort( - _utilities.Outcome(outcome_kind, ticket.code, ticket.message)) - elif ticket.sequence_number == self._lowest_unseen_sequence_number: - self._process(ticket) - else: - self._out_of_sequence_tickets[ticket.sequence_number] = ticket diff --git a/src/python/grpcio/grpc/framework/core/_termination.py b/src/python/grpcio/grpc/framework/core/_termination.py deleted file mode 100644 index fff3a3fc14..0000000000 --- a/src/python/grpcio/grpc/framework/core/_termination.py +++ /dev/null @@ -1,229 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for operation termination.""" - -import abc - -import six - -from grpc.framework.core import _constants -from grpc.framework.core import _interfaces -from grpc.framework.core import _utilities -from grpc.framework.foundation import callable_util -from grpc.framework.interfaces.base import base - - -def _invocation_completion_predicate( - unused_emission_complete, unused_transmission_complete, - unused_reception_complete, ingestion_complete): - return ingestion_complete - - -def _service_completion_predicate( - unused_emission_complete, transmission_complete, unused_reception_complete, - ingestion_complete): - return transmission_complete and ingestion_complete - - -class TerminationManager(six.with_metaclass(abc.ABCMeta, _interfaces.TerminationManager)): - """A _interfaces.TransmissionManager on which another manager may be set.""" - - @abc.abstractmethod - def set_expiration_manager(self, expiration_manager): - """Sets the expiration manager with which this manager will interact. - - Args: - expiration_manager: The _interfaces.ExpirationManager associated with the - current operation. - """ - raise NotImplementedError() - - -class _TerminationManager(TerminationManager): - """An implementation of TerminationManager.""" - - def __init__(self, predicate, action, pool): - """Constructor. - - Args: - predicate: One of _invocation_completion_predicate or - _service_completion_predicate to be used to determine when the operation - has completed. - action: A behavior to pass the operation outcome's kind on operation - termination. - pool: A thread pool. - """ - self._predicate = predicate - self._action = action - self._pool = pool - self._expiration_manager = None - - self._callbacks = [] - - self._code = None - self._details = None - self._emission_complete = False - self._transmission_complete = False - self._reception_complete = False - self._ingestion_complete = False - - # The None-ness of outcome is the operation-wide record of whether and how - # the operation has terminated. - self.outcome = None - - def set_expiration_manager(self, expiration_manager): - self._expiration_manager = expiration_manager - - def _terminate_internal_only(self, outcome): - """Terminates the operation. - - Args: - outcome: A base.Outcome describing the outcome of the operation. - """ - self.outcome = outcome - callbacks = list(self._callbacks) - self._callbacks = None - - act = callable_util.with_exceptions_logged( - self._action, _constants.INTERNAL_ERROR_LOG_MESSAGE) - - # TODO(issue 3202): Don't call the local application's callbacks if it has - # previously shown a programming defect. - if False and outcome.kind is base.Outcome.Kind.LOCAL_FAILURE: - self._pool.submit(act, base.Outcome.Kind.LOCAL_FAILURE) - else: - def call_callbacks_and_act(callbacks, outcome): - for callback in callbacks: - callback_outcome = callable_util.call_logging_exceptions( - callback, _constants.TERMINATION_CALLBACK_EXCEPTION_LOG_MESSAGE, - outcome) - if callback_outcome.exception is not None: - act_outcome_kind = base.Outcome.Kind.LOCAL_FAILURE - break - else: - act_outcome_kind = outcome.kind - act(act_outcome_kind) - - self._pool.submit( - callable_util.with_exceptions_logged( - call_callbacks_and_act, _constants.INTERNAL_ERROR_LOG_MESSAGE), - callbacks, outcome) - - def _terminate_and_notify(self, outcome): - self._terminate_internal_only(outcome) - self._expiration_manager.terminate() - - def _perhaps_complete(self): - if self._predicate( - self._emission_complete, self._transmission_complete, - self._reception_complete, self._ingestion_complete): - self._terminate_and_notify( - _utilities.Outcome( - base.Outcome.Kind.COMPLETED, self._code, self._details)) - return True - else: - return False - - def is_active(self): - """See _interfaces.TerminationManager.is_active for specification.""" - return self.outcome is None - - def add_callback(self, callback): - """See _interfaces.TerminationManager.add_callback for specification.""" - if self.outcome is None: - self._callbacks.append(callback) - return None - else: - return self.outcome - - def emission_complete(self): - """See superclass method for specification.""" - if self.outcome is None: - self._emission_complete = True - self._perhaps_complete() - - def transmission_complete(self): - """See superclass method for specification.""" - if self.outcome is None: - self._transmission_complete = True - return self._perhaps_complete() - else: - return False - - def reception_complete(self, code, details): - """See superclass method for specification.""" - if self.outcome is None: - self._reception_complete = True - self._code = code - self._details = details - self._perhaps_complete() - - def ingestion_complete(self): - """See superclass method for specification.""" - if self.outcome is None: - self._ingestion_complete = True - self._perhaps_complete() - - def expire(self): - """See _interfaces.TerminationManager.expire for specification.""" - self._terminate_internal_only( - _utilities.Outcome(base.Outcome.Kind.EXPIRED, None, None)) - - def abort(self, outcome): - """See _interfaces.TerminationManager.abort for specification.""" - self._terminate_and_notify(outcome) - - -def invocation_termination_manager(action, pool): - """Creates a TerminationManager appropriate for invocation-side use. - - Args: - action: An action to call on operation termination. - pool: A thread pool in which to execute the passed action and any - termination callbacks that are registered during the operation. - - Returns: - A TerminationManager appropriate for invocation-side use. - """ - return _TerminationManager(_invocation_completion_predicate, action, pool) - - -def service_termination_manager(action, pool): - """Creates a TerminationManager appropriate for service-side use. - - Args: - action: An action to call on operation termination. - pool: A thread pool in which to execute the passed action and any - termination callbacks that are registered during the operation. - - Returns: - A TerminationManager appropriate for service-side use. - """ - return _TerminationManager(_service_completion_predicate, action, pool) diff --git a/src/python/grpcio/grpc/framework/core/_transmission.py b/src/python/grpcio/grpc/framework/core/_transmission.py deleted file mode 100644 index 65b12c4160..0000000000 --- a/src/python/grpcio/grpc/framework/core/_transmission.py +++ /dev/null @@ -1,335 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for ticket transmission during an operation.""" - -import collections -import enum - -from grpc.framework.core import _constants -from grpc.framework.core import _interfaces -from grpc.framework.core import _utilities -from grpc.framework.foundation import callable_util -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.links import links - -_TRANSMISSION_EXCEPTION_LOG_MESSAGE = 'Exception during transmission!' - -_TRANSMISSION_FAILURE_OUTCOME = _utilities.Outcome( - base.Outcome.Kind.TRANSMISSION_FAILURE, None, None) - - -def _explode_completion(completion): - if completion is None: - return None, None, None, None - else: - return ( - completion.terminal_metadata, completion.code, completion.message, - links.Ticket.Termination.COMPLETION) - - -class _Abort( - collections.namedtuple( - '_Abort', ('kind', 'termination', 'code', 'details',))): - """Tracks whether the operation aborted and what is to be done about it. - - Attributes: - kind: A Kind value describing the overall kind of the _Abort. - termination: A links.Ticket.Termination value to be sent to the other side - of the operation. Only valid if kind is Kind.ABORTED_NOTIFY_NEEDED. - code: A code value to be sent to the other side of the operation. Only - valid if kind is Kind.ABORTED_NOTIFY_NEEDED. - details: A details value to be sent to the other side of the operation. - Only valid if kind is Kind.ABORTED_NOTIFY_NEEDED. - """ - - @enum.unique - class Kind(enum.Enum): - NOT_ABORTED = 'not aborted' - ABORTED_NOTIFY_NEEDED = 'aborted notify needed' - ABORTED_NO_NOTIFY = 'aborted no notify' - -_NOT_ABORTED = _Abort(_Abort.Kind.NOT_ABORTED, None, None, None) -_ABORTED_NO_NOTIFY = _Abort(_Abort.Kind.ABORTED_NO_NOTIFY, None, None, None) - - -class TransmissionManager(_interfaces.TransmissionManager): - """An _interfaces.TransmissionManager that sends links.Tickets.""" - - def __init__( - self, operation_id, ticket_sink, lock, pool, termination_manager): - """Constructor. - - Args: - operation_id: The operation's ID. - ticket_sink: A callable that accepts tickets and sends them to the other - side of the operation. - lock: The operation-servicing-wide lock object. - pool: A thread pool in which the work of transmitting tickets will be - performed. - termination_manager: The _interfaces.TerminationManager associated with - this operation. - """ - self._lock = lock - self._pool = pool - self._ticket_sink = ticket_sink - self._operation_id = operation_id - self._termination_manager = termination_manager - self._expiration_manager = None - - self._lowest_unused_sequence_number = 0 - self._remote_allowance = 1 - self._remote_complete = False - self._timeout = None - self._local_allowance = 0 - self._initial_metadata = None - self._payloads = [] - self._completion = None - self._abort = _NOT_ABORTED - self._transmitting = False - - def set_expiration_manager(self, expiration_manager): - """Sets the ExpirationManager with which this manager will cooperate.""" - self._expiration_manager = expiration_manager - - def _next_ticket(self): - """Creates the next ticket to be transmitted. - - Returns: - A links.Ticket to be sent to the other side of the operation or None if - there is nothing to be sent at this time. - """ - if self._abort.kind is _Abort.Kind.ABORTED_NO_NOTIFY: - return None - elif self._abort.kind is _Abort.Kind.ABORTED_NOTIFY_NEEDED: - termination = self._abort.termination - code, details = self._abort.code, self._abort.details - self._abort = _ABORTED_NO_NOTIFY - return links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, None, - None, None, None, None, None, None, code, details, termination, None) - - action = False - # TODO(nathaniel): Support other subscriptions. - local_subscription = links.Ticket.Subscription.FULL - timeout = self._timeout - if timeout is not None: - self._timeout = None - action = True - if self._local_allowance <= 0: - allowance = None - else: - allowance = self._local_allowance - self._local_allowance = 0 - action = True - initial_metadata = self._initial_metadata - if initial_metadata is not None: - self._initial_metadata = None - action = True - if not self._payloads or self._remote_allowance <= 0: - payload = None - else: - payload = self._payloads.pop(0) - self._remote_allowance -= 1 - action = True - if self._completion is None or self._payloads: - terminal_metadata, code, message, termination = None, None, None, None - else: - terminal_metadata, code, message, termination = _explode_completion( - self._completion) - self._completion = None - action = True - - if action: - ticket = links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, None, - local_subscription, timeout, allowance, initial_metadata, payload, - terminal_metadata, code, message, termination, None) - self._lowest_unused_sequence_number += 1 - return ticket - else: - return None - - def _transmit(self, ticket): - """Commences the transmission loop sending tickets. - - Args: - ticket: A links.Ticket to be sent to the other side of the operation. - """ - def transmit(ticket): - while True: - transmission_outcome = callable_util.call_logging_exceptions( - self._ticket_sink, _TRANSMISSION_EXCEPTION_LOG_MESSAGE, ticket) - if transmission_outcome.exception is None: - with self._lock: - if ticket.termination is links.Ticket.Termination.COMPLETION: - self._termination_manager.transmission_complete() - ticket = self._next_ticket() - if ticket is None: - self._transmitting = False - return - else: - with self._lock: - self._abort = _ABORTED_NO_NOTIFY - if self._termination_manager.outcome is None: - self._termination_manager.abort(_TRANSMISSION_FAILURE_OUTCOME) - self._expiration_manager.terminate() - return - - self._pool.submit(callable_util.with_exceptions_logged( - transmit, _constants.INTERNAL_ERROR_LOG_MESSAGE), ticket) - self._transmitting = True - - def kick_off( - self, group, method, timeout, protocol_options, initial_metadata, - payload, completion, allowance): - """See _interfaces.TransmissionManager.kickoff for specification.""" - # TODO(nathaniel): Support other subscriptions. - subscription = links.Ticket.Subscription.FULL - terminal_metadata, code, message, termination = _explode_completion( - completion) - self._remote_allowance = 1 if payload is None else 0 - protocol = links.Protocol(links.Protocol.Kind.CALL_OPTION, protocol_options) - ticket = links.Ticket( - self._operation_id, 0, group, method, subscription, timeout, allowance, - initial_metadata, payload, terminal_metadata, code, message, - termination, protocol) - self._lowest_unused_sequence_number = 1 - self._transmit(ticket) - - def advance(self, initial_metadata, payload, completion, allowance): - """See _interfaces.TransmissionManager.advance for specification.""" - if self._abort.kind is not _Abort.Kind.NOT_ABORTED: - return - - effective_initial_metadata = initial_metadata - effective_payload = payload - effective_completion = completion - if allowance is not None and not self._remote_complete: - effective_allowance = allowance - else: - effective_allowance = None - if self._transmitting: - if effective_initial_metadata is not None: - self._initial_metadata = effective_initial_metadata - if effective_payload is not None: - self._payloads.append(effective_payload) - if effective_completion is not None: - self._completion = effective_completion - if effective_allowance is not None: - self._local_allowance += effective_allowance - else: - if effective_payload is not None: - if 0 < self._remote_allowance: - ticket_payload = effective_payload - self._remote_allowance -= 1 - else: - self._payloads.append(effective_payload) - ticket_payload = None - else: - ticket_payload = None - if effective_completion is not None and not self._payloads: - ticket_completion = effective_completion - else: - self._completion = effective_completion - ticket_completion = None - if any( - (effective_initial_metadata, ticket_payload, ticket_completion, - effective_allowance)): - terminal_metadata, code, message, termination = _explode_completion( - completion) - ticket = links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, None, - None, None, allowance, effective_initial_metadata, ticket_payload, - terminal_metadata, code, message, termination, None) - self._lowest_unused_sequence_number += 1 - self._transmit(ticket) - - def timeout(self, timeout): - """See _interfaces.TransmissionManager.timeout for specification.""" - if self._abort.kind is not _Abort.Kind.NOT_ABORTED: - return - elif self._transmitting: - self._timeout = timeout - else: - ticket = links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, None, - None, timeout, None, None, None, None, None, None, None, None) - self._lowest_unused_sequence_number += 1 - self._transmit(ticket) - - def allowance(self, allowance): - """See _interfaces.TransmissionManager.allowance for specification.""" - if self._abort.kind is not _Abort.Kind.NOT_ABORTED: - return - elif self._transmitting or not self._payloads: - self._remote_allowance += allowance - else: - self._remote_allowance += allowance - 1 - payload = self._payloads.pop(0) - if self._payloads: - completion = None - else: - completion = self._completion - self._completion = None - terminal_metadata, code, message, termination = _explode_completion( - completion) - ticket = links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, None, - None, None, None, None, payload, terminal_metadata, code, message, - termination, None) - self._lowest_unused_sequence_number += 1 - self._transmit(ticket) - - def remote_complete(self): - """See _interfaces.TransmissionManager.remote_complete for specification.""" - self._remote_complete = True - self._local_allowance = 0 - - def abort(self, outcome): - """See _interfaces.TransmissionManager.abort for specification.""" - if self._abort.kind is _Abort.Kind.NOT_ABORTED: - if outcome is None: - self._abort = _ABORTED_NO_NOTIFY - else: - termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION.get( - outcome.kind) - if termination is None: - self._abort = _ABORTED_NO_NOTIFY - elif self._transmitting: - self._abort = _Abort( - _Abort.Kind.ABORTED_NOTIFY_NEEDED, termination, outcome.code, - outcome.details) - else: - ticket = links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, - None, None, None, None, None, None, None, outcome.code, - outcome.details, termination, None) - self._transmit(ticket) - self._abort = _ABORTED_NO_NOTIFY diff --git a/src/python/grpcio/grpc/framework/core/_utilities.py b/src/python/grpcio/grpc/framework/core/_utilities.py deleted file mode 100644 index abedc727e4..0000000000 --- a/src/python/grpcio/grpc/framework/core/_utilities.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Package-internal utilities.""" - -import collections - -from grpc.framework.interfaces.base import base - - -class ServicerPackage( - collections.namedtuple( - 'ServicerPackage', ('servicer', 'default_timeout', 'maximum_timeout'))): - """A trivial bundle class. - - Attributes: - servicer: A base.Servicer. - default_timeout: A float indicating the length of time in seconds to allow - for an operation invoked without a timeout. - maximum_timeout: A float indicating the maximum length of time in seconds to - allow for an operation. - """ - - -class Outcome( - base.Outcome, - collections.namedtuple('Outcome', ('kind', 'code', 'details',))): - """A trivial implementation of base.Outcome.""" diff --git a/src/python/grpcio/grpc/framework/core/implementations.py b/src/python/grpcio/grpc/framework/core/implementations.py deleted file mode 100644 index 364a7faed4..0000000000 --- a/src/python/grpcio/grpc/framework/core/implementations.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Entry points into the ticket-exchange-based base layer implementation.""" - -# base and links are referenced from specification in this module. -from grpc.framework.core import _end -from grpc.framework.interfaces.base import base # pylint: disable=unused-import -from grpc.framework.interfaces.links import links # pylint: disable=unused-import - - -def invocation_end_link(): - """Creates a base.End-links.Link suitable for operation invocation. - - Returns: - An object that is both a base.End and a links.Link, that supports operation - invocation, and that translates operation invocation into ticket exchange. - """ - return _end.serviceless_end_link() - - -def service_end_link(servicer, default_timeout, maximum_timeout): - """Creates a base.End-links.Link suitable for operation service. - - Args: - servicer: A base.Servicer for servicing operations. - default_timeout: A length of time in seconds to be used as the default - time alloted for a single operation. - maximum_timeout: A length of time in seconds to be used as the maximum - time alloted for a single operation. - - Returns: - An object that is both a base.End and a links.Link and that services - operations that arrive at it through ticket exchange. - """ - return _end.serviceful_end_link(servicer, default_timeout, maximum_timeout) diff --git a/src/python/grpcio/grpc/framework/crust/_calls.py b/src/python/grpcio/grpc/framework/crust/_calls.py deleted file mode 100644 index bff940d747..0000000000 --- a/src/python/grpcio/grpc/framework/crust/_calls.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Utility functions for invoking RPCs.""" - -from grpc.framework.crust import _control -from grpc.framework.interfaces.base import utilities -from grpc.framework.interfaces.face import face - -_ITERATOR_EXCEPTION_LOG_MESSAGE = 'Exception iterating over requests!' - -_EMPTY_COMPLETION = utilities.completion(None, None, None) - - -def _invoke( - end, group, method, timeout, protocol_options, initial_metadata, payload, - complete): - rendezvous = _control.Rendezvous(None, None) - subscription = utilities.full_subscription( - rendezvous, _control.protocol_receiver(rendezvous)) - operation_context, operator = end.operate( - group, method, subscription, timeout, protocol_options=protocol_options, - initial_metadata=initial_metadata, payload=payload, - completion=_EMPTY_COMPLETION if complete else None) - rendezvous.set_operator_and_context(operator, operation_context) - outcome = operation_context.add_termination_callback(rendezvous.set_outcome) - if outcome is not None: - rendezvous.set_outcome(outcome) - return rendezvous, operation_context, outcome - - -def _event_return_unary( - receiver, abortion_callback, rendezvous, operation_context, outcome, pool): - if outcome is None: - def in_pool(): - abortion = rendezvous.add_abortion_callback(abortion_callback) - if abortion is None: - try: - receiver.initial_metadata(rendezvous.initial_metadata()) - receiver.response(next(rendezvous)) - receiver.complete( - rendezvous.terminal_metadata(), rendezvous.code(), - rendezvous.details()) - except face.AbortionError: - pass - else: - abortion_callback(abortion) - pool.submit(_control.pool_wrap(in_pool, operation_context)) - return rendezvous - - -def _event_return_stream( - receiver, abortion_callback, rendezvous, operation_context, outcome, pool): - if outcome is None: - def in_pool(): - abortion = rendezvous.add_abortion_callback(abortion_callback) - if abortion is None: - try: - receiver.initial_metadata(rendezvous.initial_metadata()) - for response in rendezvous: - receiver.response(response) - receiver.complete( - rendezvous.terminal_metadata(), rendezvous.code(), - rendezvous.details()) - except face.AbortionError: - pass - else: - abortion_callback(abortion) - pool.submit(_control.pool_wrap(in_pool, operation_context)) - return rendezvous - - -def blocking_unary_unary( - end, group, method, timeout, with_call, protocol_options, initial_metadata, - payload): - """Services in a blocking fashion a unary-unary servicer method.""" - rendezvous, unused_operation_context, unused_outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, payload, - True) - if with_call: - return next(rendezvous), rendezvous - else: - return next(rendezvous) - - -def future_unary_unary( - end, group, method, timeout, protocol_options, initial_metadata, payload): - """Services a value-in value-out servicer method by returning a Future.""" - rendezvous, unused_operation_context, unused_outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, payload, - True) - return rendezvous - - -def inline_unary_stream( - end, group, method, timeout, protocol_options, initial_metadata, payload): - """Services a value-in stream-out servicer method.""" - rendezvous, unused_operation_context, unused_outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, payload, - True) - return rendezvous - - -def blocking_stream_unary( - end, group, method, timeout, with_call, protocol_options, initial_metadata, - payload_iterator, pool): - """Services in a blocking fashion a stream-in value-out servicer method.""" - rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, None, - False) - if outcome is None: - def in_pool(): - for payload in payload_iterator: - rendezvous.consume(payload) - rendezvous.terminate() - pool.submit(_control.pool_wrap(in_pool, operation_context)) - if with_call: - return next(rendezvous), rendezvous - else: - return next(rendezvous) - else: - if with_call: - return next(rendezvous), rendezvous - else: - return next(rendezvous) - - -def future_stream_unary( - end, group, method, timeout, protocol_options, initial_metadata, - payload_iterator, pool): - """Services a stream-in value-out servicer method by returning a Future.""" - rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, None, - False) - if outcome is None: - def in_pool(): - for payload in payload_iterator: - rendezvous.consume(payload) - rendezvous.terminate() - pool.submit(_control.pool_wrap(in_pool, operation_context)) - return rendezvous - - -def inline_stream_stream( - end, group, method, timeout, protocol_options, initial_metadata, - payload_iterator, pool): - """Services a stream-in stream-out servicer method.""" - rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, None, - False) - if outcome is None: - def in_pool(): - for payload in payload_iterator: - rendezvous.consume(payload) - rendezvous.terminate() - pool.submit(_control.pool_wrap(in_pool, operation_context)) - return rendezvous - - -def event_unary_unary( - end, group, method, timeout, protocol_options, initial_metadata, payload, - receiver, abortion_callback, pool): - rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, payload, - True) - return _event_return_unary( - receiver, abortion_callback, rendezvous, operation_context, outcome, pool) - - -def event_unary_stream( - end, group, method, timeout, protocol_options, initial_metadata, payload, - receiver, abortion_callback, pool): - rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, payload, - True) - return _event_return_stream( - receiver, abortion_callback, rendezvous, operation_context, outcome, pool) - - -def event_stream_unary( - end, group, method, timeout, protocol_options, initial_metadata, receiver, - abortion_callback, pool): - rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, None, - False) - return _event_return_unary( - receiver, abortion_callback, rendezvous, operation_context, outcome, pool) - - -def event_stream_stream( - end, group, method, timeout, protocol_options, initial_metadata, receiver, - abortion_callback, pool): - rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, protocol_options, initial_metadata, None, - False) - return _event_return_stream( - receiver, abortion_callback, rendezvous, operation_context, outcome, pool) diff --git a/src/python/grpcio/grpc/framework/crust/_control.py b/src/python/grpcio/grpc/framework/crust/_control.py deleted file mode 100644 index 9b4167bda0..0000000000 --- a/src/python/grpcio/grpc/framework/crust/_control.py +++ /dev/null @@ -1,584 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior for translating between sync and async control flow.""" - -import collections -import enum -import sys -import threading -import time - -from grpc.framework.foundation import abandonment -from grpc.framework.foundation import callable_util -from grpc.framework.foundation import future -from grpc.framework.foundation import stream -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.base import utilities -from grpc.framework.interfaces.face import face - -_DONE_CALLBACK_LOG_MESSAGE = 'Exception calling Future "done" callback!' -_INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Crust) Internal Error! )-:' - -_CANNOT_SET_INITIAL_METADATA = ( - 'Could not set initial metadata - has it already been set, or has a ' + - 'payload already been sent?') -_CANNOT_SET_TERMINAL_METADATA = ( - 'Could not set terminal metadata - has it already been set, or has RPC ' + - 'completion already been indicated?') -_CANNOT_SET_CODE = ( - 'Could not set code - has it already been set, or has RPC completion ' + - 'already been indicated?') -_CANNOT_SET_DETAILS = ( - 'Could not set details - has it already been set, or has RPC completion ' + - 'already been indicated?') - - -class _DummyOperator(base.Operator): - - def advance( - self, initial_metadata=None, payload=None, completion=None, - allowance=None): - pass - -_DUMMY_OPERATOR = _DummyOperator() - - -class _Awaited( - collections.namedtuple('_Awaited', ('kind', 'value',))): - - @enum.unique - class Kind(enum.Enum): - NOT_YET_ARRIVED = 'not yet arrived' - ARRIVED = 'arrived' - -_NOT_YET_ARRIVED = _Awaited(_Awaited.Kind.NOT_YET_ARRIVED, None) -_ARRIVED_AND_NONE = _Awaited(_Awaited.Kind.ARRIVED, None) - - -class _Transitory( - collections.namedtuple('_Transitory', ('kind', 'value',))): - - @enum.unique - class Kind(enum.Enum): - NOT_YET_SEEN = 'not yet seen' - PRESENT = 'present' - GONE = 'gone' - -_NOT_YET_SEEN = _Transitory(_Transitory.Kind.NOT_YET_SEEN, None) -_GONE = _Transitory(_Transitory.Kind.GONE, None) - - -class _Termination( - collections.namedtuple( - '_Termination', ('terminated', 'abortion', 'abortion_error',))): - """Values indicating whether and how an RPC has terminated. - - Attributes: - terminated: A boolean indicating whether or not the RPC has terminated. - abortion: A face.Abortion value describing the RPC's abortion or None if the - RPC did not abort. - abortion_error: A face.AbortionError describing the RPC's abortion or None - if the RPC did not abort. - """ - -_NOT_TERMINATED = _Termination(False, None, None) - -_OPERATION_OUTCOME_KIND_TO_TERMINATION_CONSTRUCTOR = { - base.Outcome.Kind.COMPLETED: lambda *unused_args: _Termination( - True, None, None), - base.Outcome.Kind.CANCELLED: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.CANCELLED, *args), - face.CancellationError(*args)), - base.Outcome.Kind.EXPIRED: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.EXPIRED, *args), - face.ExpirationError(*args)), - base.Outcome.Kind.LOCAL_SHUTDOWN: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.LOCAL_SHUTDOWN, *args), - face.LocalShutdownError(*args)), - base.Outcome.Kind.REMOTE_SHUTDOWN: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.REMOTE_SHUTDOWN, *args), - face.RemoteShutdownError(*args)), - base.Outcome.Kind.RECEPTION_FAILURE: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.NETWORK_FAILURE, *args), - face.NetworkError(*args)), - base.Outcome.Kind.TRANSMISSION_FAILURE: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.NETWORK_FAILURE, *args), - face.NetworkError(*args)), - base.Outcome.Kind.LOCAL_FAILURE: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.LOCAL_FAILURE, *args), - face.LocalError(*args)), - base.Outcome.Kind.REMOTE_FAILURE: lambda *args: _Termination( - True, face.Abortion(face.Abortion.Kind.REMOTE_FAILURE, *args), - face.RemoteError(*args)), -} - - -def _wait_once_until(condition, until): - if until is None: - condition.wait() - else: - remaining = until - time.time() - if remaining < 0: - raise future.TimeoutError() - else: - condition.wait(timeout=remaining) - - -def _done_callback_as_operation_termination_callback( - done_callback, rendezvous): - def operation_termination_callback(operation_outcome): - rendezvous.set_outcome(operation_outcome) - done_callback(rendezvous) - return operation_termination_callback - - -def _abortion_callback_as_operation_termination_callback( - rpc_abortion_callback, rendezvous_set_outcome): - def operation_termination_callback(operation_outcome): - termination = rendezvous_set_outcome(operation_outcome) - if termination.abortion is not None: - rpc_abortion_callback(termination.abortion) - return operation_termination_callback - - -class Rendezvous(base.Operator, future.Future, stream.Consumer, face.Call): - """A rendez-vous for the threads of an operation. - - Instances of this object present iterator and stream.Consumer interfaces for - interacting with application code and present a base.Operator interface and - maintain a base.Operator internally for interacting with base interface code. - """ - - def __init__(self, operator, operation_context): - self._condition = threading.Condition() - - self._operator = operator - self._operation_context = operation_context - - self._protocol_context = _NOT_YET_ARRIVED - - self._up_initial_metadata = _NOT_YET_ARRIVED - self._up_payload = None - self._up_allowance = 1 - self._up_completion = _NOT_YET_ARRIVED - self._down_initial_metadata = _NOT_YET_SEEN - self._down_payload = None - self._down_allowance = 1 - self._down_terminal_metadata = _NOT_YET_SEEN - self._down_code = _NOT_YET_SEEN - self._down_details = _NOT_YET_SEEN - - self._termination = _NOT_TERMINATED - - # The semantics of future.Future.cancel and future.Future.cancelled are - # slightly wonky, so they have to be tracked separately from the rest of the - # result of the RPC. This field tracks whether cancellation was requested - # prior to termination of the RPC - self._cancelled = False - - def set_operator_and_context(self, operator, operation_context): - with self._condition: - self._operator = operator - self._operation_context = operation_context - - def _down_completion(self): - if self._down_terminal_metadata.kind is _Transitory.Kind.NOT_YET_SEEN: - terminal_metadata = None - self._down_terminal_metadata = _GONE - elif self._down_terminal_metadata.kind is _Transitory.Kind.PRESENT: - terminal_metadata = self._down_terminal_metadata.value - self._down_terminal_metadata = _GONE - else: - terminal_metadata = None - if self._down_code.kind is _Transitory.Kind.NOT_YET_SEEN: - code = None - self._down_code = _GONE - elif self._down_code.kind is _Transitory.Kind.PRESENT: - code = self._down_code.value - self._down_code = _GONE - else: - code = None - if self._down_details.kind is _Transitory.Kind.NOT_YET_SEEN: - details = None - self._down_details = _GONE - elif self._down_details.kind is _Transitory.Kind.PRESENT: - details = self._down_details.value - self._down_details = _GONE - else: - details = None - return utilities.completion(terminal_metadata, code, details) - - def _set_outcome(self, outcome): - if not self._termination.terminated: - self._operator = _DUMMY_OPERATOR - self._operation_context = None - self._down_initial_metadata = _GONE - self._down_payload = None - self._down_terminal_metadata = _GONE - self._down_code = _GONE - self._down_details = _GONE - - if self._up_initial_metadata.kind is _Awaited.Kind.NOT_YET_ARRIVED: - initial_metadata = None - else: - initial_metadata = self._up_initial_metadata.value - if self._up_completion.kind is _Awaited.Kind.NOT_YET_ARRIVED: - terminal_metadata = None - else: - terminal_metadata = self._up_completion.value.terminal_metadata - if outcome.kind is base.Outcome.Kind.COMPLETED: - code = self._up_completion.value.code - details = self._up_completion.value.message - else: - code = outcome.code - details = outcome.details - self._termination = _OPERATION_OUTCOME_KIND_TO_TERMINATION_CONSTRUCTOR[ - outcome.kind](initial_metadata, terminal_metadata, code, details) - - self._condition.notify_all() - - return self._termination - - def advance( - self, initial_metadata=None, payload=None, completion=None, - allowance=None): - with self._condition: - if initial_metadata is not None: - self._up_initial_metadata = _Awaited( - _Awaited.Kind.ARRIVED, initial_metadata) - if payload is not None: - if self._up_initial_metadata.kind is _Awaited.Kind.NOT_YET_ARRIVED: - self._up_initial_metadata = _ARRIVED_AND_NONE - self._up_payload = payload - self._up_allowance -= 1 - if completion is not None: - if self._up_initial_metadata.kind is _Awaited.Kind.NOT_YET_ARRIVED: - self._up_initial_metadata = _ARRIVED_AND_NONE - self._up_completion = _Awaited( - _Awaited.Kind.ARRIVED, completion) - if allowance is not None: - if self._down_payload is not None: - self._operator.advance(payload=self._down_payload) - self._down_payload = None - self._down_allowance += allowance - 1 - else: - self._down_allowance += allowance - self._condition.notify_all() - - def cancel(self): - with self._condition: - if self._operation_context is not None: - self._operation_context.cancel() - self._cancelled = True - return False - - def cancelled(self): - with self._condition: - return self._cancelled - - def running(self): - with self._condition: - return not self._termination.terminated - - def done(self): - with self._condition: - return self._termination.terminated - - def result(self, timeout=None): - until = None if timeout is None else time.time() + timeout - with self._condition: - while True: - if self._termination.terminated: - if self._termination.abortion is None: - return self._up_payload - elif self._termination.abortion.kind is face.Abortion.Kind.CANCELLED: - raise future.CancelledError() - else: - raise self._termination.abortion_error # pylint: disable=raising-bad-type - else: - _wait_once_until(self._condition, until) - - def exception(self, timeout=None): - until = None if timeout is None else time.time() + timeout - with self._condition: - while True: - if self._termination.terminated: - if self._termination.abortion is None: - return None - else: - return self._termination.abortion_error - else: - _wait_once_until(self._condition, until) - - def traceback(self, timeout=None): - until = None if timeout is None else time.time() + timeout - with self._condition: - while True: - if self._termination.terminated: - if self._termination.abortion_error is None: - return None - else: - abortion_error = self._termination.abortion_error - break - else: - _wait_once_until(self._condition, until) - - try: - raise abortion_error - except face.AbortionError: - return sys.exc_info()[2] - - def add_done_callback(self, fn): - with self._condition: - if self._operation_context is not None: - outcome = self._operation_context.add_termination_callback( - _done_callback_as_operation_termination_callback(fn, self)) - if outcome is None: - return - else: - self._set_outcome(outcome) - - fn(self) - - def consume(self, value): - with self._condition: - while True: - if self._termination.terminated: - return - elif 0 < self._down_allowance: - self._operator.advance(payload=value) - self._down_allowance -= 1 - return - else: - self._condition.wait() - - def terminate(self): - with self._condition: - if self._termination.terminated: - return - elif self._down_code.kind is _Transitory.Kind.GONE: - # Conform to specified idempotence of terminate by ignoring extra calls. - return - else: - completion = self._down_completion() - self._operator.advance(completion=completion) - - def consume_and_terminate(self, value): - with self._condition: - while True: - if self._termination.terminated: - return - elif 0 < self._down_allowance: - completion = self._down_completion() - self._operator.advance(payload=value, completion=completion) - return - else: - self._condition.wait() - - def __iter__(self): - return self - - def __next__(self): - return self.next() - - def next(self): - with self._condition: - while True: - if self._termination.abortion_error is not None: - raise self._termination.abortion_error - elif self._up_payload is not None: - payload = self._up_payload - self._up_payload = None - if self._up_completion.kind is _Awaited.Kind.NOT_YET_ARRIVED: - self._operator.advance(allowance=1) - return payload - elif self._up_completion.kind is _Awaited.Kind.ARRIVED: - raise StopIteration() - else: - self._condition.wait() - - def is_active(self): - with self._condition: - return not self._termination.terminated - - def time_remaining(self): - if self._operation_context is None: - return 0 - else: - return self._operation_context.time_remaining() - - def add_abortion_callback(self, abortion_callback): - with self._condition: - if self._operation_context is None: - return self._termination.abortion - else: - outcome = self._operation_context.add_termination_callback( - _abortion_callback_as_operation_termination_callback( - abortion_callback, self.set_outcome)) - if outcome is not None: - return self._set_outcome(outcome).abortion - else: - return self._termination.abortion - - def protocol_context(self): - with self._condition: - while True: - if self._protocol_context.kind is _Awaited.Kind.ARRIVED: - return self._protocol_context.value - elif self._termination.abortion_error is not None: - raise self._termination.abortion_error - else: - self._condition.wait() - - def initial_metadata(self): - with self._condition: - while True: - if self._up_initial_metadata.kind is _Awaited.Kind.ARRIVED: - return self._up_initial_metadata.value - elif self._termination.terminated: - return None - else: - self._condition.wait() - - def terminal_metadata(self): - with self._condition: - while True: - if self._up_completion.kind is _Awaited.Kind.ARRIVED: - return self._up_completion.value.terminal_metadata - elif self._termination.terminated: - return None - else: - self._condition.wait() - - def code(self): - with self._condition: - while True: - if self._up_completion.kind is _Awaited.Kind.ARRIVED: - return self._up_completion.value.code - elif self._termination.terminated: - return None - else: - self._condition.wait() - - def details(self): - with self._condition: - while True: - if self._up_completion.kind is _Awaited.Kind.ARRIVED: - return self._up_completion.value.message - elif self._termination.terminated: - return None - else: - self._condition.wait() - - def set_initial_metadata(self, initial_metadata): - with self._condition: - if (self._down_initial_metadata.kind is not - _Transitory.Kind.NOT_YET_SEEN): - raise ValueError(_CANNOT_SET_INITIAL_METADATA) - else: - self._down_initial_metadata = _GONE - self._operator.advance(initial_metadata=initial_metadata) - - def set_terminal_metadata(self, terminal_metadata): - with self._condition: - if (self._down_terminal_metadata.kind is not - _Transitory.Kind.NOT_YET_SEEN): - raise ValueError(_CANNOT_SET_TERMINAL_METADATA) - else: - self._down_terminal_metadata = _Transitory( - _Transitory.Kind.PRESENT, terminal_metadata) - - def set_code(self, code): - with self._condition: - if self._down_code.kind is not _Transitory.Kind.NOT_YET_SEEN: - raise ValueError(_CANNOT_SET_CODE) - else: - self._down_code = _Transitory(_Transitory.Kind.PRESENT, code) - - def set_details(self, details): - with self._condition: - if self._down_details.kind is not _Transitory.Kind.NOT_YET_SEEN: - raise ValueError(_CANNOT_SET_DETAILS) - else: - self._down_details = _Transitory(_Transitory.Kind.PRESENT, details) - - def set_protocol_context(self, protocol_context): - with self._condition: - self._protocol_context = _Awaited( - _Awaited.Kind.ARRIVED, protocol_context) - self._condition.notify_all() - - def set_outcome(self, outcome): - with self._condition: - return self._set_outcome(outcome) - - -class _ProtocolReceiver(base.ProtocolReceiver): - - def __init__(self, rendezvous): - self._rendezvous = rendezvous - - def context(self, protocol_context): - self._rendezvous.set_protocol_context(protocol_context) - - -def protocol_receiver(rendezvous): - return _ProtocolReceiver(rendezvous) - - -def pool_wrap(behavior, operation_context): - """Wraps an operation-related behavior so that it may be called in a pool. - - Args: - behavior: A callable related to carrying out an operation. - operation_context: A base_interfaces.OperationContext for the operation. - - Returns: - A callable that when called carries out the behavior of the given callable - and handles whatever exceptions it raises appropriately. - """ - def translation(*args): - try: - behavior(*args) - except ( - abandonment.Abandoned, - face.CancellationError, - face.ExpirationError, - face.LocalShutdownError, - face.RemoteShutdownError, - face.NetworkError, - face.RemoteError, - ) as e: - if operation_context.outcome() is None: - operation_context.fail(e) - except Exception as e: - operation_context.fail(e) - return callable_util.with_exceptions_logged( - translation, _INTERNAL_ERROR_LOG_MESSAGE) diff --git a/src/python/grpcio/grpc/framework/crust/_service.py b/src/python/grpcio/grpc/framework/crust/_service.py deleted file mode 100644 index 9903415c09..0000000000 --- a/src/python/grpcio/grpc/framework/crust/_service.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Behaviors for servicing RPCs.""" - -from grpc.framework.crust import _control -from grpc.framework.foundation import abandonment -from grpc.framework.interfaces.base import utilities -from grpc.framework.interfaces.face import face - - -class _ServicerContext(face.ServicerContext): - - def __init__(self, rendezvous): - self._rendezvous = rendezvous - - def is_active(self): - return self._rendezvous.is_active() - - def time_remaining(self): - return self._rendezvous.time_remaining() - - def add_abortion_callback(self, abortion_callback): - return self._rendezvous.add_abortion_callback(abortion_callback) - - def cancel(self): - self._rendezvous.cancel() - - def protocol_context(self): - return self._rendezvous.protocol_context() - - def invocation_metadata(self): - return self._rendezvous.initial_metadata() - - def initial_metadata(self, initial_metadata): - self._rendezvous.set_initial_metadata(initial_metadata) - - def terminal_metadata(self, terminal_metadata): - self._rendezvous.set_terminal_metadata(terminal_metadata) - - def code(self, code): - self._rendezvous.set_code(code) - - def details(self, details): - self._rendezvous.set_details(details) - - -def _adaptation(pool, in_pool): - def adaptation(operator, operation_context): - rendezvous = _control.Rendezvous(operator, operation_context) - subscription = utilities.full_subscription( - rendezvous, _control.protocol_receiver(rendezvous)) - outcome = operation_context.add_termination_callback(rendezvous.set_outcome) - if outcome is None: - pool.submit(_control.pool_wrap(in_pool, operation_context), rendezvous) - return subscription - else: - raise abandonment.Abandoned() - return adaptation - - -def adapt_inline_unary_unary(method, pool): - def in_pool(rendezvous): - request = next(rendezvous) - response = method(request, _ServicerContext(rendezvous)) - rendezvous.consume_and_terminate(response) - return _adaptation(pool, in_pool) - - -def adapt_inline_unary_stream(method, pool): - def in_pool(rendezvous): - request = next(rendezvous) - response_iterator = method(request, _ServicerContext(rendezvous)) - for response in response_iterator: - rendezvous.consume(response) - rendezvous.terminate() - return _adaptation(pool, in_pool) - - -def adapt_inline_stream_unary(method, pool): - def in_pool(rendezvous): - response = method(rendezvous, _ServicerContext(rendezvous)) - rendezvous.consume_and_terminate(response) - return _adaptation(pool, in_pool) - - -def adapt_inline_stream_stream(method, pool): - def in_pool(rendezvous): - response_iterator = method(rendezvous, _ServicerContext(rendezvous)) - for response in response_iterator: - rendezvous.consume(response) - rendezvous.terminate() - return _adaptation(pool, in_pool) - - -def adapt_event_unary_unary(method, pool): - def in_pool(rendezvous): - request = next(rendezvous) - method( - request, rendezvous.consume_and_terminate, _ServicerContext(rendezvous)) - return _adaptation(pool, in_pool) - - -def adapt_event_unary_stream(method, pool): - def in_pool(rendezvous): - request = next(rendezvous) - method(request, rendezvous, _ServicerContext(rendezvous)) - return _adaptation(pool, in_pool) - - -def adapt_event_stream_unary(method, pool): - def in_pool(rendezvous): - request_consumer = method( - rendezvous.consume_and_terminate, _ServicerContext(rendezvous)) - for request in rendezvous: - request_consumer.consume(request) - request_consumer.terminate() - return _adaptation(pool, in_pool) - - -def adapt_event_stream_stream(method, pool): - def in_pool(rendezvous): - request_consumer = method(rendezvous, _ServicerContext(rendezvous)) - for request in rendezvous: - request_consumer.consume(request) - request_consumer.terminate() - return _adaptation(pool, in_pool) - - -def adapt_multi_method(multi_method, pool): - def adaptation(group, method, operator, operation_context): - rendezvous = _control.Rendezvous(operator, operation_context) - subscription = utilities.full_subscription( - rendezvous, _control.protocol_receiver(rendezvous)) - outcome = operation_context.add_termination_callback(rendezvous.set_outcome) - if outcome is None: - def in_pool(): - request_consumer = multi_method.service( - group, method, rendezvous, _ServicerContext(rendezvous)) - for request in rendezvous: - request_consumer.consume(request) - request_consumer.terminate() - pool.submit(_control.pool_wrap(in_pool, operation_context), rendezvous) - return subscription - else: - raise abandonment.Abandoned() - return adaptation diff --git a/src/python/grpcio/grpc/framework/crust/implementations.py b/src/python/grpcio/grpc/framework/crust/implementations.py deleted file mode 100644 index 2d3ab733b6..0000000000 --- a/src/python/grpcio/grpc/framework/crust/implementations.py +++ /dev/null @@ -1,366 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Entry points into the Crust layer of RPC Framework.""" - -import six - -from grpc.framework.common import cardinality -from grpc.framework.common import style -from grpc.framework.crust import _calls -from grpc.framework.crust import _service -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.face import face - - -class _BaseServicer(base.Servicer): - - def __init__(self, adapted_methods, adapted_multi_method): - self._adapted_methods = adapted_methods - self._adapted_multi_method = adapted_multi_method - - def service(self, group, method, context, output_operator): - adapted_method = self._adapted_methods.get((group, method), None) - if adapted_method is not None: - return adapted_method(output_operator, context) - elif self._adapted_multi_method is not None: - try: - return self._adapted_multi_method( - group, method, output_operator, context) - except face.NoSuchMethodError: - raise base.NoSuchMethodError(None, None) - else: - raise base.NoSuchMethodError(None, None) - - -class _UnaryUnaryMultiCallable(face.UnaryUnaryMultiCallable): - - def __init__(self, end, group, method, pool): - self._end = end - self._group = group - self._method = method - self._pool = pool - - def __call__( - self, request, timeout, metadata=None, with_call=False, - protocol_options=None): - return _calls.blocking_unary_unary( - self._end, self._group, self._method, timeout, with_call, - protocol_options, metadata, request) - - def future(self, request, timeout, metadata=None, protocol_options=None): - return _calls.future_unary_unary( - self._end, self._group, self._method, timeout, protocol_options, - metadata, request) - - def event( - self, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - return _calls.event_unary_unary( - self._end, self._group, self._method, timeout, protocol_options, - metadata, request, receiver, abortion_callback, self._pool) - - -class _UnaryStreamMultiCallable(face.UnaryStreamMultiCallable): - - def __init__(self, end, group, method, pool): - self._end = end - self._group = group - self._method = method - self._pool = pool - - def __call__(self, request, timeout, metadata=None, protocol_options=None): - return _calls.inline_unary_stream( - self._end, self._group, self._method, timeout, protocol_options, - metadata, request) - - def event( - self, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - return _calls.event_unary_stream( - self._end, self._group, self._method, timeout, protocol_options, - metadata, request, receiver, abortion_callback, self._pool) - - -class _StreamUnaryMultiCallable(face.StreamUnaryMultiCallable): - - def __init__(self, end, group, method, pool): - self._end = end - self._group = group - self._method = method - self._pool = pool - - def __call__( - self, request_iterator, timeout, metadata=None, - with_call=False, protocol_options=None): - return _calls.blocking_stream_unary( - self._end, self._group, self._method, timeout, with_call, - protocol_options, metadata, request_iterator, self._pool) - - def future( - self, request_iterator, timeout, metadata=None, protocol_options=None): - return _calls.future_stream_unary( - self._end, self._group, self._method, timeout, protocol_options, - metadata, request_iterator, self._pool) - - def event( - self, receiver, abortion_callback, timeout, metadata=None, - protocol_options=None): - return _calls.event_stream_unary( - self._end, self._group, self._method, timeout, protocol_options, - metadata, receiver, abortion_callback, self._pool) - - -class _StreamStreamMultiCallable(face.StreamStreamMultiCallable): - - def __init__(self, end, group, method, pool): - self._end = end - self._group = group - self._method = method - self._pool = pool - - def __call__( - self, request_iterator, timeout, metadata=None, protocol_options=None): - return _calls.inline_stream_stream( - self._end, self._group, self._method, timeout, protocol_options, - metadata, request_iterator, self._pool) - - def event( - self, receiver, abortion_callback, timeout, metadata=None, - protocol_options=None): - return _calls.event_stream_stream( - self._end, self._group, self._method, timeout, protocol_options, - metadata, receiver, abortion_callback, self._pool) - - -class _GenericStub(face.GenericStub): - """An face.GenericStub implementation.""" - - def __init__(self, end, pool): - self._end = end - self._pool = pool - - def blocking_unary_unary( - self, group, method, request, timeout, metadata=None, - with_call=None, protocol_options=None): - return _calls.blocking_unary_unary( - self._end, group, method, timeout, with_call, protocol_options, - metadata, request) - - def future_unary_unary( - self, group, method, request, timeout, metadata=None, - protocol_options=None): - return _calls.future_unary_unary( - self._end, group, method, timeout, protocol_options, metadata, request) - - def inline_unary_stream( - self, group, method, request, timeout, metadata=None, - protocol_options=None): - return _calls.inline_unary_stream( - self._end, group, method, timeout, protocol_options, metadata, request) - - def blocking_stream_unary( - self, group, method, request_iterator, timeout, metadata=None, - with_call=None, protocol_options=None): - return _calls.blocking_stream_unary( - self._end, group, method, timeout, with_call, protocol_options, - metadata, request_iterator, self._pool) - - def future_stream_unary( - self, group, method, request_iterator, timeout, metadata=None, - protocol_options=None): - return _calls.future_stream_unary( - self._end, group, method, timeout, protocol_options, metadata, - request_iterator, self._pool) - - def inline_stream_stream( - self, group, method, request_iterator, timeout, metadata=None, - protocol_options=None): - return _calls.inline_stream_stream( - self._end, group, method, timeout, protocol_options, metadata, - request_iterator, self._pool) - - def event_unary_unary( - self, group, method, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - return _calls.event_unary_unary( - self._end, group, method, timeout, protocol_options, metadata, request, - receiver, abortion_callback, self._pool) - - def event_unary_stream( - self, group, method, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - return _calls.event_unary_stream( - self._end, group, method, timeout, protocol_options, metadata, request, - receiver, abortion_callback, self._pool) - - def event_stream_unary( - self, group, method, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - return _calls.event_stream_unary( - self._end, group, method, timeout, protocol_options, metadata, receiver, - abortion_callback, self._pool) - - def event_stream_stream( - self, group, method, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - return _calls.event_stream_stream( - self._end, group, method, timeout, protocol_options, metadata, receiver, - abortion_callback, self._pool) - - def unary_unary(self, group, method): - return _UnaryUnaryMultiCallable(self._end, group, method, self._pool) - - def unary_stream(self, group, method): - return _UnaryStreamMultiCallable(self._end, group, method, self._pool) - - def stream_unary(self, group, method): - return _StreamUnaryMultiCallable(self._end, group, method, self._pool) - - def stream_stream(self, group, method): - return _StreamStreamMultiCallable(self._end, group, method, self._pool) - - -class _DynamicStub(face.DynamicStub): - """An face.DynamicStub implementation.""" - - def __init__(self, end, group, cardinalities, pool): - self._end = end - self._group = group - self._cardinalities = cardinalities - self._pool = pool - - def __getattr__(self, attr): - method_cardinality = self._cardinalities.get(attr) - if method_cardinality is cardinality.Cardinality.UNARY_UNARY: - return _UnaryUnaryMultiCallable(self._end, self._group, attr, self._pool) - elif method_cardinality is cardinality.Cardinality.UNARY_STREAM: - return _UnaryStreamMultiCallable(self._end, self._group, attr, self._pool) - elif method_cardinality is cardinality.Cardinality.STREAM_UNARY: - return _StreamUnaryMultiCallable(self._end, self._group, attr, self._pool) - elif method_cardinality is cardinality.Cardinality.STREAM_STREAM: - return _StreamStreamMultiCallable( - self._end, self._group, attr, self._pool) - else: - raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr) - - -def _adapt_method_implementations(method_implementations, pool): - adapted_implementations = {} - for name, method_implementation in six.iteritems(method_implementations): - if method_implementation.style is style.Service.INLINE: - if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - adapted_implementations[name] = _service.adapt_inline_unary_unary( - method_implementation.unary_unary_inline, pool) - elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - adapted_implementations[name] = _service.adapt_inline_unary_stream( - method_implementation.unary_stream_inline, pool) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - adapted_implementations[name] = _service.adapt_inline_stream_unary( - method_implementation.stream_unary_inline, pool) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - adapted_implementations[name] = _service.adapt_inline_stream_stream( - method_implementation.stream_stream_inline, pool) - elif method_implementation.style is style.Service.EVENT: - if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - adapted_implementations[name] = _service.adapt_event_unary_unary( - method_implementation.unary_unary_event, pool) - elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - adapted_implementations[name] = _service.adapt_event_unary_stream( - method_implementation.unary_stream_event, pool) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - adapted_implementations[name] = _service.adapt_event_stream_unary( - method_implementation.stream_unary_event, pool) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - adapted_implementations[name] = _service.adapt_event_stream_stream( - method_implementation.stream_stream_event, pool) - return adapted_implementations - - -def servicer(method_implementations, multi_method_implementation, pool): - """Creates a base.Servicer. - - It is guaranteed that any passed face.MultiMethodImplementation will - only be called to service an RPC if there is no - face.MethodImplementation for the RPC method in the passed - method_implementations dictionary. - - Args: - method_implementations: A dictionary from RPC method name to - face.MethodImplementation object to be used to service the named - RPC method. - multi_method_implementation: An face.MultiMethodImplementation to be - used to service any RPCs not serviced by the - face.MethodImplementations given in the method_implementations - dictionary, or None. - pool: A thread pool. - - Returns: - A base.Servicer that services RPCs via the given implementations. - """ - adapted_implementations = _adapt_method_implementations( - method_implementations, pool) - if multi_method_implementation is None: - adapted_multi_method_implementation = None - else: - adapted_multi_method_implementation = _service.adapt_multi_method( - multi_method_implementation, pool) - return _BaseServicer( - adapted_implementations, adapted_multi_method_implementation) - - -def generic_stub(end, pool): - """Creates an face.GenericStub. - - Args: - end: A base.End. - pool: A futures.ThreadPoolExecutor. - - Returns: - A face.GenericStub that performs RPCs via the given base.End. - """ - return _GenericStub(end, pool) - - -def dynamic_stub(end, group, cardinalities, pool): - """Creates an face.DynamicStub. - - Args: - end: A base.End. - group: The group identifier for all RPCs to be made with the created - face.DynamicStub. - cardinalities: A dict from method identifier to cardinality.Cardinality - value identifying the cardinality of every RPC method to be supported by - the created face.DynamicStub. - pool: A futures.ThreadPoolExecutor. - - Returns: - A face.DynamicStub that performs RPCs via the given base.End. - """ - return _DynamicStub(end, group, cardinalities, pool) diff --git a/src/python/grpcio/grpc/framework/foundation/_timer_future.py b/src/python/grpcio/grpc/framework/foundation/_timer_future.py deleted file mode 100644 index 2c9996aa9d..0000000000 --- a/src/python/grpcio/grpc/framework/foundation/_timer_future.py +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Affords a Future implementation based on Python's threading.Timer.""" - -import sys -import threading -import time - -from grpc.framework.foundation import future - - -class TimerFuture(future.Future): - """A Future implementation based around Timer objects.""" - - def __init__(self, compute_time, computation): - """Constructor. - - Args: - compute_time: The time after which to begin this future's computation. - computation: The computation to be performed within this Future. - """ - self._lock = threading.Lock() - self._compute_time = compute_time - self._computation = computation - self._timer = None - self._computing = False - self._computed = False - self._cancelled = False - self._result = None - self._exception = None - self._traceback = None - self._waiting = [] - - def _compute(self): - """Performs the computation embedded in this Future. - - Or doesn't, if the time to perform it has not yet arrived. - """ - with self._lock: - time_remaining = self._compute_time - time.time() - if 0 < time_remaining: - self._timer = threading.Timer(time_remaining, self._compute) - self._timer.start() - return - else: - self._computing = True - - try: - return_value = self._computation() - exception = None - traceback = None - except Exception as e: # pylint: disable=broad-except - return_value = None - exception = e - traceback = sys.exc_info()[2] - - with self._lock: - self._computing = False - self._computed = True - self._return_value = return_value - self._exception = exception - self._traceback = traceback - waiting = self._waiting - - for callback in waiting: - callback(self) - - def start(self): - """Starts this Future. - - This must be called exactly once, immediately after construction. - """ - with self._lock: - self._timer = threading.Timer( - self._compute_time - time.time(), self._compute) - self._timer.start() - - def cancel(self): - """See future.Future.cancel for specification.""" - with self._lock: - if self._computing or self._computed: - return False - elif self._cancelled: - return True - else: - self._timer.cancel() - self._cancelled = True - waiting = self._waiting - - for callback in waiting: - try: - callback(self) - except Exception: # pylint: disable=broad-except - pass - - return True - - def cancelled(self): - """See future.Future.cancelled for specification.""" - with self._lock: - return self._cancelled - - def running(self): - """See future.Future.running for specification.""" - with self._lock: - return not self._computed and not self._cancelled - - def done(self): - """See future.Future.done for specification.""" - with self._lock: - return self._computed or self._cancelled - - def result(self, timeout=None): - """See future.Future.result for specification.""" - with self._lock: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - if self._exception is None: - return self._return_value - else: - raise self._exception # pylint: disable=raising-bad-type - - condition = threading.Condition() - def notify_condition(unused_future): - with condition: - condition.notify() - self._waiting.append(notify_condition) - - with condition: - condition.wait(timeout=timeout) - - with self._lock: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - if self._exception is None: - return self._return_value - else: - raise self._exception # pylint: disable=raising-bad-type - else: - raise future.TimeoutError() - - def exception(self, timeout=None): - """See future.Future.exception for specification.""" - with self._lock: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - return self._exception - - condition = threading.Condition() - def notify_condition(unused_future): - with condition: - condition.notify() - self._waiting.append(notify_condition) - - with condition: - condition.wait(timeout=timeout) - - with self._lock: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - return self._exception - else: - raise future.TimeoutError() - - def traceback(self, timeout=None): - """See future.Future.traceback for specification.""" - with self._lock: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - return self._traceback - - condition = threading.Condition() - def notify_condition(unused_future): - with condition: - condition.notify() - self._waiting.append(notify_condition) - - with condition: - condition.wait(timeout=timeout) - - with self._lock: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - return self._traceback - else: - raise future.TimeoutError() - - def add_done_callback(self, fn): - """See future.Future.add_done_callback for specification.""" - with self._lock: - if not self._computed and not self._cancelled: - self._waiting.append(fn) - return - - fn(self) diff --git a/src/python/grpcio/grpc/framework/foundation/activated.py b/src/python/grpcio/grpc/framework/foundation/activated.py deleted file mode 100644 index 8b8e4f45b5..0000000000 --- a/src/python/grpcio/grpc/framework/foundation/activated.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Interfaces related to streams of values or objects.""" - -import abc - -import six - -class Activated(six.with_metaclass(abc.ABCMeta)): - """Interface for objects that may be started and stopped. - - Values implementing this type must also implement the context manager - protocol. - """ - - @abc.abstractmethod - def __enter__(self): - """See the context manager protocol for specification.""" - raise NotImplementedError() - - @abc.abstractmethod - def __exit__(self, exc_type, exc_val, exc_tb): - """See the context manager protocol for specification.""" - raise NotImplementedError() - - @abc.abstractmethod - def start(self): - """Activates this object. - - Returns: - A value equal to the value returned by this object's __enter__ method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def stop(self): - """Deactivates this object.""" - raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/foundation/later.py b/src/python/grpcio/grpc/framework/foundation/later.py deleted file mode 100644 index 1d1e065041..0000000000 --- a/src/python/grpcio/grpc/framework/foundation/later.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Enables scheduling execution at a later time.""" - -import time - -from grpc.framework.foundation import _timer_future - - -def later(delay, computation): - """Schedules later execution of a callable. - - Args: - delay: Any numeric value. Represents the minimum length of time in seconds - to allow to pass before beginning the computation. No guarantees are made - about the maximum length of time that will pass. - computation: A callable that accepts no arguments. - - Returns: - A Future representing the scheduled computation. - """ - timer_future = _timer_future.TimerFuture(time.time() + delay, computation) - timer_future.start() - return timer_future diff --git a/src/python/grpcio/grpc/framework/foundation/relay.py b/src/python/grpcio/grpc/framework/foundation/relay.py deleted file mode 100644 index 20f41b2738..0000000000 --- a/src/python/grpcio/grpc/framework/foundation/relay.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Implementations of in-order work deference.""" - -import abc -import enum -import threading - -from grpc.framework.foundation import activated -from grpc.framework.foundation import logging_pool - -_NULL_BEHAVIOR = lambda unused_value: None - - -class Relay(object): - """Performs work submitted to it in another thread. - - Performs work in the order in which work was submitted to it; otherwise there - would be no reason to use an implementation of this interface instead of a - thread pool. - """ - - @abc.abstractmethod - def add_value(self, value): - """Adds a value to be passed to the behavior registered with this Relay. - - Args: - value: A value that will be passed to a call made in another thread to the - behavior registered with this Relay. - """ - raise NotImplementedError() - - @abc.abstractmethod - def set_behavior(self, behavior): - """Sets the behavior that this Relay should call when passed values. - - Args: - behavior: The behavior that this Relay should call in another thread when - passed a value, or None to have passed values ignored. - """ - raise NotImplementedError() - - -class _PoolRelay(activated.Activated, Relay): - - @enum.unique - class _State(enum.Enum): - INACTIVE = 'inactive' - IDLE = 'idle' - SPINNING = 'spinning' - - def __init__(self, pool, behavior): - self._condition = threading.Condition() - self._pool = pool - self._own_pool = pool is None - self._state = _PoolRelay._State.INACTIVE - self._activated = False - self._spinning = False - self._values = [] - self._behavior = _NULL_BEHAVIOR if behavior is None else behavior - - def _spin(self, behavior, value): - while True: - behavior(value) - with self._condition: - if self._values: - value = self._values.pop(0) - behavior = self._behavior - else: - self._state = _PoolRelay._State.IDLE - self._condition.notify_all() - break - - def add_value(self, value): - with self._condition: - if self._state is _PoolRelay._State.INACTIVE: - raise ValueError('add_value not valid on inactive Relay!') - elif self._state is _PoolRelay._State.IDLE: - self._pool.submit(self._spin, self._behavior, value) - self._state = _PoolRelay._State.SPINNING - else: - self._values.append(value) - - def set_behavior(self, behavior): - with self._condition: - self._behavior = _NULL_BEHAVIOR if behavior is None else behavior - - def _start(self): - with self._condition: - self._state = _PoolRelay._State.IDLE - if self._own_pool: - self._pool = logging_pool.pool(1) - return self - - def _stop(self): - with self._condition: - while self._state is _PoolRelay._State.SPINNING: - self._condition.wait() - if self._own_pool: - self._pool.shutdown(wait=True) - self._state = _PoolRelay._State.INACTIVE - - def __enter__(self): - return self._start() - - def __exit__(self, exc_type, exc_val, exc_tb): - self._stop() - return False - - def start(self): - return self._start() - - def stop(self): - self._stop() - - -def relay(behavior): - """Creates a Relay. - - Args: - behavior: The behavior to be called by the created Relay, or None to have - passed values dropped until a different behavior is given to the returned - Relay later. - - Returns: - An object that is both an activated.Activated and a Relay. The object is - only valid for use as a Relay when activated. - """ - return _PoolRelay(None, behavior) - - -def pool_relay(pool, behavior): - """Creates a Relay that uses a given thread pool. - - This object will make use of at most one thread in the given pool. - - Args: - pool: A futures.ThreadPoolExecutor for use by the created Relay. - behavior: The behavior to be called by the created Relay, or None to have - passed values dropped until a different behavior is given to the returned - Relay later. - - Returns: - An object that is both an activated.Activated and a Relay. The object is - only valid for use as a Relay when activated. - """ - return _PoolRelay(pool, behavior) diff --git a/src/python/grpcio/grpc/framework/interfaces/links/__init__.py b/src/python/grpcio/grpc/framework/interfaces/links/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio/grpc/framework/interfaces/links/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio/grpc/framework/interfaces/links/links.py b/src/python/grpcio/grpc/framework/interfaces/links/links.py deleted file mode 100644 index 9631b19078..0000000000 --- a/src/python/grpcio/grpc/framework/interfaces/links/links.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""The low-level ticket-exchanging-links interface of RPC Framework.""" - -import abc -import collections -import enum - -import six - - -class Protocol(collections.namedtuple('Protocol', ('kind', 'value',))): - """A sum type for handles to a system that transmits tickets. - - Attributes: - kind: A Kind value identifying the kind of value being passed. - value: The value being passed between the high-level application and the - system affording ticket transport. - """ - - @enum.unique - class Kind(enum.Enum): - CALL_OPTION = 'call option' - SERVICER_CONTEXT = 'servicer context' - INVOCATION_CONTEXT = 'invocation context' - - -class Ticket( - collections.namedtuple( - 'Ticket', - ('operation_id', 'sequence_number', 'group', 'method', 'subscription', - 'timeout', 'allowance', 'initial_metadata', 'payload', - 'terminal_metadata', 'code', 'message', 'termination', 'protocol',))): - """A sum type for all values sent from a front to a back. - - Attributes: - operation_id: A unique-with-respect-to-equality hashable object identifying - a particular operation. - sequence_number: A zero-indexed integer sequence number identifying the - ticket's place in the stream of tickets sent in one direction for the - particular operation. - group: The group to which the method of the operation belongs. Must be - present in the first ticket from invocation side to service side. Ignored - for all other tickets exchanged during the operation. - method: The name of an operation. Must be present in the first ticket from - invocation side to service side. Ignored for all other tickets exchanged - during the operation. - subscription: A Subscription value describing the interest one side has in - receiving information from the other side. Must be present in the first - ticket from either side. Ignored for all other tickets exchanged during - the operation. - timeout: A nonzero length of time (measured from the beginning of the - operation) to allow for the entire operation. Must be present in the first - ticket from invocation side to service side. Optional for all other - tickets exchanged during the operation. Receipt of a value from the other - side of the operation indicates the value in use by that side. Setting a - value on a later ticket allows either side to request time extensions (or - even time reductions!) on in-progress operations. - allowance: A positive integer granting permission for a number of payloads - to be transmitted to the communicating side of the operation, or None if - no additional allowance is being granted with this ticket. - initial_metadata: An optional metadata value communicated from one side to - the other at the beginning of the operation. May be non-None in at most - one ticket from each side. Any non-None value must appear no later than - the first payload value. - payload: A customer payload object. May be None. - terminal_metadata: A metadata value comminicated from one side to the other - at the end of the operation. May be non-None in the same ticket as - the code and message, but must be None for all earlier tickets. - code: A value communicated at operation completion. May be None. - message: A value communicated at operation completion. May be None. - termination: A Termination value describing the end of the operation, or - None if the operation has not yet terminated. If set, no further tickets - may be sent in the same direction. - protocol: A Protocol value or None, with further semantics being a matter - between high-level application and underlying ticket transport. - """ - - @enum.unique - class Subscription(enum.Enum): - """Identifies the level of subscription of a side of an operation.""" - - NONE = 'none' - TERMINATION = 'termination' - FULL = 'full' - - @enum.unique - class Termination(enum.Enum): - """Identifies the termination of an operation.""" - - COMPLETION = 'completion' - CANCELLATION = 'cancellation' - EXPIRATION = 'expiration' - SHUTDOWN = 'shutdown' - RECEPTION_FAILURE = 'reception failure' - TRANSMISSION_FAILURE = 'transmission failure' - LOCAL_FAILURE = 'local failure' - REMOTE_FAILURE = 'remote failure' - - -class Link(six.with_metaclass(abc.ABCMeta)): - """Accepts and emits tickets.""" - - @abc.abstractmethod - def accept_ticket(self, ticket): - """Accept a Ticket. - - Args: - ticket: Any Ticket. - """ - raise NotImplementedError() - - @abc.abstractmethod - def join_link(self, link): - """Mates this object with a peer with which it will exchange tickets.""" - raise NotImplementedError() diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 0f4db9d972..d1e2d418c3 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='0.16.0.dev0' +VERSION='1.0.0rc1' diff --git a/src/python/grpcio/support.py b/src/python/grpcio/support.py index 33244eb388..7730374df0 100644 --- a/src/python/grpcio/support.py +++ b/src/python/grpcio/support.py @@ -50,7 +50,6 @@ Could not find <Python.h>. This could mean the following: (check your environment variables or try re-installing?) * You're on Windows and your Python installation was somehow corrupted (check your environment variables or try re-installing?) - * Note: Windows users should look into installing `vcpython27`. """ C_CHECKS = { diff --git a/src/python/grpcio_health_checking/MANIFEST.in b/src/python/grpcio_health_checking/MANIFEST.in index 7d26647697..7407f646d1 100644 --- a/src/python/grpcio_health_checking/MANIFEST.in +++ b/src/python/grpcio_health_checking/MANIFEST.in @@ -1,3 +1,4 @@ +include grpc_version.py include health_commands.py -graft grpc_health +graft grpc global-exclude *.pyc diff --git a/src/python/grpcio/grpc/framework/crust/__init__.py b/src/python/grpcio_health_checking/grpc/__init__.py index 7086519106..fcc7048815 100644 --- a/src/python/grpcio/grpc/framework/crust/__init__.py +++ b/src/python/grpcio_health_checking/grpc/__init__.py @@ -27,4 +27,4 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +__import__('pkg_resources').declare_namespace(__name__) diff --git a/src/python/grpcio/grpc/_adapter/__init__.py b/src/python/grpcio_health_checking/grpc/health/__init__.py index 7086519106..7086519106 100644 --- a/src/python/grpcio/grpc/_adapter/__init__.py +++ b/src/python/grpcio_health_checking/grpc/health/__init__.py diff --git a/src/python/grpcio/grpc/_links/__init__.py b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py index 7086519106..7086519106 100644 --- a/src/python/grpcio/grpc/_links/__init__.py +++ b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/health.py b/src/python/grpcio_health_checking/grpc/health/v1/health.py index 8da60c70cb..8108ac1096 100644 --- a/src/python/grpcio_health_checking/grpc_health/health/v1/health.py +++ b/src/python/grpcio_health_checking/grpc/health/v1/health.py @@ -31,10 +31,12 @@ import threading -from grpc_health.health.v1 import health_pb2 +import grpc +from grpc.health.v1 import health_pb2 -class HealthServicer(health_pb2.BetaHealthServicer): + +class HealthServicer(health_pb2.HealthServicer): """Servicer handling RPCs for service statuses.""" def __init__(self): @@ -43,14 +45,12 @@ class HealthServicer(health_pb2.BetaHealthServicer): def Check(self, request, context): with self._server_status_lock: - if request.service not in self._server_status: - # TODO(atash): once the Python API has a way of setting the server - # status, bring us into conformance with the health check spec by - # returning the NOT_FOUND status here. - raise NotImplementedError() + status = self._server_status.get(request.service) + if status is None: + context.set_code(grpc.StatusCode.NOT_FOUND) + return health_pb2.HealthCheckResponse() else: - return health_pb2.HealthCheckResponse( - status=self._server_status[request.service]) + return health_pb2.HealthCheckResponse(status=status) def set(self, service, status): """Sets the status of a service. @@ -63,4 +63,3 @@ class HealthServicer(health_pb2.BetaHealthServicer): """ with self._server_status_lock: self._server_status[service] = status - diff --git a/src/python/grpcio_health_checking/grpc_health/health/__init__.py b/src/python/grpcio_health_checking/grpc_health/health/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc_health/health/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_health_checking/grpc_health/__init__.py b/src/python/grpcio_health_checking/grpc_version.py index 7086519106..2e48fde893 100644 --- a/src/python/grpcio_health_checking/grpc_health/__init__.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -1,4 +1,4 @@ -# Copyright 2015, Google Inc. +# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,4 +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. +# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! +VERSION='1.0.0rc1' diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py index a7a59f6974..66df25da63 100644 --- a/src/python/grpcio_health_checking/health_commands.py +++ b/src/python/grpcio_health_checking/health_commands.py @@ -29,16 +29,10 @@ """Provides distutils command classes for the GRPC Python setup process.""" -import distutils -import glob import os -import os.path import shutil -import subprocess -import sys import setuptools -from setuptools.command import build_py ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto') @@ -60,12 +54,25 @@ class CopyProtoModules(setuptools.Command): if os.path.isfile(HEALTH_PROTO): shutil.copyfile( HEALTH_PROTO, - os.path.join(ROOT_DIR, 'grpc_health/health/v1/health.proto')) + os.path.join(ROOT_DIR, 'grpc/health/v1/health.proto')) -class BuildPy(build_py.build_py): - """Custom project build command.""" +class BuildPackageProtos(setuptools.Command): + """Command to generate project *_pb2.py modules from proto files.""" + + description = 'build grpc protobuf modules' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass def run(self): - self.run_command('build_proto_modules') - build_py.build_py.run(self) + # due to limitations of the proto generator, we require that only *one* + # directory is provided as an 'include' directory. We assume it's the '' key + # to `self.distribution.package_dir` (and get a key error if it's not + # there). + from grpc.tools import command + command.build_package_protos(self.distribution.package_dir['']) diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py index 70b4575bf5..727d628885 100644 --- a/src/python/grpcio_health_checking/setup.py +++ b/src/python/grpcio_health_checking/setup.py @@ -30,49 +30,42 @@ """Setup module for the GRPC Python package's optional health checking.""" import os -import os.path import sys -from distutils import core as _core import setuptools -import grpc.tools.command - # Ensure we're in the proper directory whether or not we're being used by pip. os.chdir(os.path.dirname(os.path.abspath(__file__))) # Break import-style to ensure we can actually find our commands module. import health_commands - -PACKAGES = ( - setuptools.find_packages('.') -) +import grpc_version PACKAGE_DIRECTORIES = { '': '.', } SETUP_REQUIRES = ( - 'grpcio-tools>=0.14.0', + 'grpcio-tools>=0.15.0', ) INSTALL_REQUIRES = ( - 'grpcio>=0.13.1', + 'grpcio>=0.15.0', ) COMMAND_CLASS = { # Run preprocess from the repository *before* doing any packaging! 'preprocess': health_commands.CopyProtoModules, - - 'build_proto_modules': grpc.tools.command.BuildProtoModules, - 'build_py': health_commands.BuildPy, + 'build_package_protos': health_commands.BuildPackageProtos, } setuptools.setup( name='grpcio-health-checking', - version='0.14.0', - packages=list(PACKAGES), + version=grpc_version.VERSION, + license='3-clause BSD', package_dir=PACKAGE_DIRECTORIES, + packages=setuptools.find_packages('.'), + namespace_packages=['grpc'], install_requires=INSTALL_REQUIRES, setup_requires=SETUP_REQUIRES, cmdclass=COMMAND_CLASS diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index 171829b62f..5ee551cfe1 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -138,7 +138,7 @@ class BuildPy(build_py.build_py): def run(self): try: - self.run_command('build_proto_modules') + self.run_command('build_package_protos') except CommandError as error: sys.stderr.write('warning: %s\n' % error.message) build_py.build_py.run(self) diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 7aa600728a..a2387857c6 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION='0.16.0.dev0' +VERSION='1.0.0rc1' diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py index 7eef420bdb..0afaf7dfa2 100644 --- a/src/python/grpcio_tests/setup.py +++ b/src/python/grpcio_tests/setup.py @@ -75,7 +75,7 @@ COMMAND_CLASS = { # Run `preprocess` *before* doing any packaging! 'preprocess': commands.GatherProto, - 'build_proto_modules': grpc.tools.command.BuildProtoModules, + 'build_package_protos': grpc.tools.command.BuildPackageProtos, 'build_py': commands.BuildPy, 'run_interop': commands.RunInterop, 'test_lite': commands.TestLite diff --git a/src/python/grpcio_tests/tests/_runner.py b/src/python/grpcio_tests/tests/_runner.py index f0718573e2..926dcbe23a 100644 --- a/src/python/grpcio_tests/tests/_runner.py +++ b/src/python/grpcio_tests/tests/_runner.py @@ -30,7 +30,6 @@ from __future__ import absolute_import import collections -import fcntl import multiprocessing import os import select @@ -178,15 +177,20 @@ class Runner(object): stderr_pipe.write_bypass( '\ninterrupted stderr:\n{}\n'.format(stderr_pipe.output().decode())) os._exit(1) - signal.signal(signal.SIGINT, sigint_handler) - signal.signal(signal.SIGSEGV, fault_handler) - signal.signal(signal.SIGBUS, fault_handler) - signal.signal(signal.SIGABRT, fault_handler) - signal.signal(signal.SIGFPE, fault_handler) - signal.signal(signal.SIGILL, fault_handler) + def try_set_handler(name, handler): + try: + signal.signal(getattr(signal, name), handler) + except AttributeError: + pass + try_set_handler('SIGINT', sigint_handler) + try_set_handler('SIGSEGV', fault_handler) + try_set_handler('SIGBUS', fault_handler) + try_set_handler('SIGABRT', fault_handler) + try_set_handler('SIGFPE', fault_handler) + try_set_handler('SIGILL', fault_handler) # Sometimes output will lag after a test has successfully finished; we # ignore such writes to our pipes. - signal.signal(signal.SIGPIPE, signal.SIG_IGN) + try_set_handler('SIGPIPE', signal.SIG_IGN) # Run the tests result.startTestRun() diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py index 1b63388663..80300d13df 100644 --- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py @@ -27,48 +27,68 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Tests of grpc_health.health.v1.health.""" +"""Tests of grpc.health.v1.health.""" import unittest -from grpc_health.health.v1 import health -from grpc_health.health.v1 import health_pb2 +import grpc +from grpc.framework.foundation import logging_pool +from grpc.health.v1 import health +from grpc.health.v1 import health_pb2 + +from tests.unit.framework.common import test_constants class HealthServicerTest(unittest.TestCase): def setUp(self): - self.servicer = health.HealthServicer() - self.servicer.set('', health_pb2.HealthCheckResponse.SERVING) - self.servicer.set('grpc.test.TestServiceServing', - health_pb2.HealthCheckResponse.SERVING) - self.servicer.set('grpc.test.TestServiceUnknown', - health_pb2.HealthCheckResponse.UNKNOWN) - self.servicer.set('grpc.test.TestServiceNotServing', - health_pb2.HealthCheckResponse.NOT_SERVING) + servicer = health.HealthServicer() + servicer.set('', health_pb2.HealthCheckResponse.SERVING) + servicer.set('grpc.test.TestServiceServing', + health_pb2.HealthCheckResponse.SERVING) + servicer.set('grpc.test.TestServiceUnknown', + health_pb2.HealthCheckResponse.UNKNOWN) + servicer.set('grpc.test.TestServiceNotServing', + health_pb2.HealthCheckResponse.NOT_SERVING) + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server(server_pool) + port = self._server.add_insecure_port('[::]:0') + health_pb2.add_HealthServicer_to_server(servicer, self._server) + self._server.start() + + channel = grpc.insecure_channel('localhost:%d' % port) + self._stub = health_pb2.HealthStub(channel) def test_empty_service(self): request = health_pb2.HealthCheckRequest() - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) def test_serving_service(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceServing') - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) def test_unknown_serivce(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceUnknown') - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.UNKNOWN) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status) def test_not_serving_service(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceNotServing') - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.NOT_SERVING) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, resp.status) + + def test_not_found_service(self): + request = health_pb2.HealthCheckRequest( + service='not-found') + with self.assertRaises(grpc.RpcError) as context: + resp = self._stub.Check(request) + + self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code()) if __name__ == '__main__': diff --git a/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py b/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py index 91519b6fba..c753d6faf0 100644 --- a/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py +++ b/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py @@ -48,7 +48,7 @@ class InsecureInteropTest( port = self.server.add_insecure_port('[::]:0') self.server.start() self.stub = test_pb2.beta_create_TestService_stub( - implementations.insecure_channel('[::]', port)) + implementations.insecure_channel('localhost', port)) def tearDown(self): self.server.stop(0) diff --git a/src/python/grpcio_tests/tests/interop/_secure_interop_test.py b/src/python/grpcio_tests/tests/interop/_secure_interop_test.py index c61547b977..cb09f54a34 100644 --- a/src/python/grpcio_tests/tests/interop/_secure_interop_test.py +++ b/src/python/grpcio_tests/tests/interop/_secure_interop_test.py @@ -55,7 +55,7 @@ class SecureInteropTest( self.server.start() self.stub = test_pb2.beta_create_TestService_stub( test_utilities.not_really_secure_channel( - '[::]', port, implementations.ssl_channel_credentials( + 'localhost', port, implementations.ssl_channel_credentials( resources.test_root_certificates()), _SERVER_HOST_OVERRIDE)) diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py index 86aa0495a2..97e6c9e27e 100644 --- a/src/python/grpcio_tests/tests/interop/methods.py +++ b/src/python/grpcio_tests/tests/interop/methods.py @@ -39,6 +39,7 @@ import time from oauth2client import client as oauth2client_client +import grpc from grpc.beta import implementations from grpc.beta import interfaces from grpc.framework.common import cardinality @@ -57,12 +58,18 @@ class TestService(test_pb2.BetaTestServiceServicer): return empty_pb2.Empty() def UnaryCall(self, request, context): + if request.HasField('response_status'): + context.code(request.response_status.code) + context.details(request.response_status.message) return messages_pb2.SimpleResponse( payload=messages_pb2.Payload( type=messages_pb2.COMPRESSABLE, body=b'\x00' * request.response_size)) def StreamingOutputCall(self, request, context): + if request.HasField('response_status'): + context.code(request.response_status.code) + context.details(request.response_status.message) for response_parameters in request.response_parameters: yield messages_pb2.StreamingOutputCallResponse( payload=messages_pb2.Payload( @@ -79,6 +86,9 @@ class TestService(test_pb2.BetaTestServiceServicer): def FullDuplexCall(self, request_iterator, context): for request in request_iterator: + if request.HasField('response_status'): + context.code(request.response_status.code) + context.details(request.response_status.message) for response_parameters in request.response_parameters: yield messages_pb2.StreamingOutputCallResponse( payload=messages_pb2.Payload( @@ -289,6 +299,39 @@ def _empty_stream(stub): pass +def _status_code_and_message(stub): + with stub: + message = 'test status message' + code = 2 + status = grpc.StatusCode.UNKNOWN # code = 2 + request = messages_pb2.SimpleRequest( + response_type=messages_pb2.COMPRESSABLE, + response_size=1, + payload=messages_pb2.Payload(body=b'\x00'), + response_status=messages_pb2.EchoStatus(code=code, message=message) + ) + response_future = stub.UnaryCall.future(request, _TIMEOUT) + if response_future.code() != status: + raise ValueError( + 'expected code %s, got %s' % (status, response_future.code())) + if response_future.details() != message: + raise ValueError( + 'expected message %s, got %s' % (message, response_future.details())) + + request = messages_pb2.StreamingOutputCallRequest( + response_type=messages_pb2.COMPRESSABLE, + response_parameters=( + messages_pb2.ResponseParameters(size=1),), + response_status=messages_pb2.EchoStatus(code=code, message=message)) + response_iterator = stub.StreamingOutputCall(request, _TIMEOUT) + if response_future.code() != status: + raise ValueError( + 'expected code %s, got %s' % (status, response_iterator.code())) + if response_future.details() != message: + raise ValueError( + 'expected message %s, got %s' % (message, response_iterator.details())) + + def _compute_engine_creds(stub, args): response = _large_unary_common_behavior(stub, True, True) if args.default_service_account != response.username: @@ -347,6 +390,7 @@ class TestCase(enum.Enum): CANCEL_AFTER_BEGIN = 'cancel_after_begin' CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response' EMPTY_STREAM = 'empty_stream' + STATUS_CODE_AND_MESSAGE = 'status_code_and_message' COMPUTE_ENGINE_CREDS = 'compute_engine_creds' OAUTH2_AUTH_TOKEN = 'oauth2_auth_token' JWT_TOKEN_CREDS = 'jwt_token_creds' @@ -372,6 +416,8 @@ class TestCase(enum.Enum): _timeout_on_sleeping_server(stub) elif self is TestCase.EMPTY_STREAM: _empty_stream(stub) + elif self is TestCase.STATUS_CODE_AND_MESSAGE: + _status_code_and_message(stub) elif self is TestCase.COMPUTE_ENGINE_CREDS: _compute_engine_creds(stub, args) elif self is TestCase.OAUTH2_AUTH_TOKEN: diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py index bf09380c85..7ca2bcff38 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py @@ -171,7 +171,7 @@ def _CreateService(): return servicer_methods.HalfDuplexCall(request_iter, context) server = grpc.server( - (), futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) + futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) port = server.add_insecure_port('[::]:0') server.start() @@ -192,7 +192,7 @@ def _CreateIncompleteService(): pass server = grpc.server( - (), futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) + futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) port = server.add_insecure_port('[::]:0') server.start() diff --git a/src/python/grpcio_tests/tests/qps/benchmark_client.py b/src/python/grpcio_tests/tests/qps/benchmark_client.py index 080281415d..83b46c914e 100644 --- a/src/python/grpcio_tests/tests/qps/benchmark_client.py +++ b/src/python/grpcio_tests/tests/qps/benchmark_client.py @@ -37,16 +37,23 @@ from concurrent import futures from six.moves import queue import grpc -from grpc.beta import implementations -from grpc.framework.interfaces.face import face from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import services_pb2 from tests.unit import resources -from tests.unit.beta import test_utilities +from tests.unit import test_common _TIMEOUT = 60 * 60 * 24 +class GenericStub(object): + + def __init__(self, channel): + self.UnaryCall = channel.unary_unary( + '/grpc.testing.BenchmarkService/UnaryCall') + self.StreamingCall = channel.stream_stream( + '/grpc.testing.BenchmarkService/StreamingCall') + + class BenchmarkClient: """Benchmark client interface that exposes a non-blocking send_request().""" @@ -54,15 +61,12 @@ class BenchmarkClient: def __init__(self, server, config, hist): # Create the stub - host, port = server.split(':') - port = int(port) if config.HasField('security_params'): - creds = implementations.ssl_channel_credentials( - resources.test_root_certificates()) - channel = test_utilities.not_really_secure_channel( - host, port, creds, config.security_params.server_host_override) + creds = grpc.ssl_channel_credentials(resources.test_root_certificates()) + channel = test_common.test_secure_channel( + server, creds, config.security_params.server_host_override) else: - channel = implementations.insecure_channel(host, port) + channel = grpc.insecure_channel(server) connected_event = threading.Event() def wait_for_ready(connectivity): @@ -73,7 +77,7 @@ class BenchmarkClient: if config.payload_config.WhichOneof('payload') == 'simple_params': self._generic = False - self._stub = services_pb2.beta_create_BenchmarkService_stub(channel) + self._stub = services_pb2.BenchmarkServiceStub(channel) payload = messages_pb2.Payload( body='\0' * config.payload_config.simple_params.req_size) self._request = messages_pb2.SimpleRequest( @@ -81,7 +85,7 @@ class BenchmarkClient: response_size=config.payload_config.simple_params.resp_size) else: self._generic = True - self._stub = implementations.generic_stub(channel) + self._stub = GenericStub(channel) self._request = '\0' * config.payload_config.bytebuf_params.req_size self._hist = hist @@ -166,13 +170,8 @@ class _SyncStream(object): def start(self): self._is_streaming = True - if self._generic: - stream_callable = self._stub.stream_stream( - 'grpc.testing.BenchmarkService', 'StreamingCall') - else: - stream_callable = self._stub.StreamingCall - - response_stream = stream_callable(self._request_generator(), _TIMEOUT) + response_stream = self._stub.StreamingCall( + self._request_generator(), _TIMEOUT) for _ in response_stream: self._handle_response( self, time.time() - self._send_time_queue.get_nowait()) diff --git a/src/python/grpcio_tests/tests/qps/benchmark_server.py b/src/python/grpcio_tests/tests/qps/benchmark_server.py index 8cbf480d58..2b76b810cd 100644 --- a/src/python/grpcio_tests/tests/qps/benchmark_server.py +++ b/src/python/grpcio_tests/tests/qps/benchmark_server.py @@ -31,7 +31,7 @@ from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import services_pb2 -class BenchmarkServer(services_pb2.BetaBenchmarkServiceServicer): +class BenchmarkServer(services_pb2.BenchmarkServiceServicer): """Synchronous Server implementation for the Benchmark service.""" def UnaryCall(self, request, context): @@ -44,7 +44,7 @@ class BenchmarkServer(services_pb2.BetaBenchmarkServiceServicer): yield messages_pb2.SimpleResponse(payload=payload) -class GenericBenchmarkServer(services_pb2.BetaBenchmarkServiceServicer): +class GenericBenchmarkServer(services_pb2.BenchmarkServiceServicer): """Generic Server implementation for the Benchmark service.""" def __init__(self, resp_size): diff --git a/src/python/grpcio_tests/tests/qps/qps_worker.py b/src/python/grpcio_tests/tests/qps/qps_worker.py index 16926379a5..2371ff0956 100644 --- a/src/python/grpcio_tests/tests/qps/qps_worker.py +++ b/src/python/grpcio_tests/tests/qps/qps_worker.py @@ -32,18 +32,21 @@ import argparse import time +from concurrent import futures +import grpc from src.proto.grpc.testing import services_pb2 from tests.qps import worker_server def run_worker_server(port): + server = grpc.server(futures.ThreadPoolExecutor(max_workers=5)) servicer = worker_server.WorkerServer() - server = services_pb2.beta_create_WorkerService_server(servicer) + services_pb2.add_WorkerServiceServicer_to_server(servicer, server) server.add_insecure_port('[::]:{}'.format(port)) server.start() servicer.wait_for_quit() - server.stop(2) + server.stop(0) if __name__ == '__main__': diff --git a/src/python/grpcio_tests/tests/qps/worker_server.py b/src/python/grpcio_tests/tests/qps/worker_server.py index d41f8377c2..46d542940f 100644 --- a/src/python/grpcio_tests/tests/qps/worker_server.py +++ b/src/python/grpcio_tests/tests/qps/worker_server.py @@ -32,8 +32,8 @@ import random import threading import time -from grpc.beta import implementations -from grpc.framework.interfaces.face import utilities +from concurrent import futures +import grpc from src.proto.grpc.testing import control_pb2 from src.proto.grpc.testing import services_pb2 from src.proto.grpc.testing import stats_pb2 @@ -45,7 +45,7 @@ from tests.qps import histogram from tests.unit import resources -class WorkerServer(services_pb2.BetaWorkerServiceServicer): +class WorkerServer(services_pb2.WorkerServiceServicer): """Python Worker Server implementation.""" def __init__(self): @@ -65,7 +65,7 @@ class WorkerServer(services_pb2.BetaWorkerServiceServicer): if request.mark.reset: start_time = end_time yield status - server.stop(0) + server.stop(None) def _get_server_status(self, start_time, end_time, port, cores): end_time = time.time() @@ -76,25 +76,35 @@ class WorkerServer(services_pb2.BetaWorkerServiceServicer): return control_pb2.ServerStatus(stats=stats, port=port, cores=cores) def _create_server(self, config): - if config.server_type == control_pb2.SYNC_SERVER: + if config.async_server_threads == 0: + # This is the default concurrent.futures thread pool size, but + # None doesn't seem to work + server_threads = multiprocessing.cpu_count() * 5 + else: + server_threads = config.async_server_threads + server = grpc.server(futures.ThreadPoolExecutor( + max_workers=server_threads)) + if config.server_type == control_pb2.ASYNC_SERVER: servicer = benchmark_server.BenchmarkServer() - server = services_pb2.beta_create_BenchmarkService_server(servicer) + services_pb2.add_BenchmarkServiceServicer_to_server(servicer, server) elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER: resp_size = config.payload_config.bytebuf_params.resp_size servicer = benchmark_server.GenericBenchmarkServer(resp_size) method_implementations = { - ('grpc.testing.BenchmarkService', 'StreamingCall'): - utilities.stream_stream_inline(servicer.StreamingCall), - ('grpc.testing.BenchmarkService', 'UnaryCall'): - utilities.unary_unary_inline(servicer.UnaryCall), + 'StreamingCall': + grpc.stream_stream_rpc_method_handler(servicer.StreamingCall), + 'UnaryCall': + grpc.unary_unary_rpc_method_handler(servicer.UnaryCall), } - server = implementations.server(method_implementations) + handler = grpc.method_handlers_generic_handler( + 'grpc.testing.BenchmarkService', method_implementations) + server.add_generic_rpc_handlers((handler,)) else: raise Exception('Unsupported server type {}'.format(config.server_type)) if config.HasField('security_params'): # Use SSL - server_creds = implementations.ssl_server_credentials([( - resources.private_key(), resources.certificate_chain())]) + server_creds = grpc.ssl_server_credentials( + ((resources.private_key(), resources.certificate_chain()),)) port = server.add_secure_port('[::]:{}'.format(config.port), server_creds) else: port = server.add_insecure_port('[::]:{}'.format(config.port)) diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json index 45eb75b242..dcaef0db1f 100644 --- a/src/python/grpcio_tests/tests/tests.json +++ b/src/python/grpcio_tests/tests/tests.json @@ -12,6 +12,7 @@ "_channel_test.ChannelTest", "_compression_test.CompressionTest", "_connectivity_channel_test.ConnectivityStatesTest", + "_credentials_test.CredentialsTest", "_empty_message_test.EmptyMessageTest", "_exit_test.ExitTest", "_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest", diff --git a/src/python/grpcio_tests/tests/unit/_adapter/.gitignore b/src/python/grpcio_tests/tests/unit/_adapter/.gitignore deleted file mode 100644 index a6f96cd6db..0000000000 --- a/src/python/grpcio_tests/tests/unit/_adapter/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.a -*.so -*.dll -*.pyc -*.pyd diff --git a/src/python/grpcio_tests/tests/unit/_adapter/__init__.py b/src/python/grpcio_tests/tests/unit/_adapter/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_tests/tests/unit/_adapter/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_tests/tests/unit/_adapter/_proto_scenarios.py b/src/python/grpcio_tests/tests/unit/_adapter/_proto_scenarios.py deleted file mode 100644 index 7a90eacf77..0000000000 --- a/src/python/grpcio_tests/tests/unit/_adapter/_proto_scenarios.py +++ /dev/null @@ -1,262 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Test scenarios using protocol buffers.""" - -import abc -import threading - -import six - -from tests.unit._junkdrawer import math_pb2 - - -class ProtoScenario(six.with_metaclass(abc.ABCMeta)): - """An RPC test scenario using protocol buffers.""" - - @abc.abstractmethod - def method(self): - """Access the test method name. - - Returns: - The test method name. - """ - raise NotImplementedError() - - @abc.abstractmethod - def serialize_request(self, request): - """Serialize a request protocol buffer. - - Args: - request: A request protocol buffer. - - Returns: - The bytestring serialization of the given request protocol buffer. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_request(self, request_bytestring): - """Deserialize a request protocol buffer. - - Args: - request_bytestring: The bytestring serialization of a request protocol - buffer. - - Returns: - The request protocol buffer deserialized from the given byte string. - """ - raise NotImplementedError() - - @abc.abstractmethod - def serialize_response(self, response): - """Serialize a response protocol buffer. - - Args: - response: A response protocol buffer. - - Returns: - The bytestring serialization of the given response protocol buffer. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_response(self, response_bytestring): - """Deserialize a response protocol buffer. - - Args: - response_bytestring: The bytestring serialization of a response protocol - buffer. - - Returns: - The response protocol buffer deserialized from the given byte string. - """ - raise NotImplementedError() - - @abc.abstractmethod - def requests(self): - """Access the sequence of requests for this scenario. - - Returns: - A sequence of request protocol buffers. - """ - raise NotImplementedError() - - @abc.abstractmethod - def response_for_request(self, request): - """Access the response for a particular request. - - Args: - request: A request protocol buffer. - - Returns: - The response protocol buffer appropriate for the given request. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify_requests(self, experimental_requests): - """Verify the requests transmitted through the system under test. - - Args: - experimental_requests: The request protocol buffers transmitted through - the system under test. - - Returns: - True if the requests satisfy this test scenario; False otherwise. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify_responses(self, experimental_responses): - """Verify the responses transmitted through the system under test. - - Args: - experimental_responses: The response protocol buffers transmitted through - the system under test. - - Returns: - True if the responses satisfy this test scenario; False otherwise. - """ - raise NotImplementedError() - - -class EmptyScenario(ProtoScenario): - """A scenario that transmits no protocol buffers in either direction.""" - - def method(self): - return 'DivMany' - - def serialize_request(self, request): - raise ValueError('This should not be necessary to call!') - - def deserialize_request(self, request_bytestring): - raise ValueError('This should not be necessary to call!') - - def serialize_response(self, response): - raise ValueError('This should not be necessary to call!') - - def deserialize_response(self, response_bytestring): - raise ValueError('This should not be necessary to call!') - - def requests(self): - return () - - def response_for_request(self, request): - raise ValueError('This should not be necessary to call!') - - def verify_requests(self, experimental_requests): - return not experimental_requests - - def verify_responses(self, experimental_responses): - return not experimental_responses - - -class BidirectionallyUnaryScenario(ProtoScenario): - """A scenario that transmits no protocol buffers in either direction.""" - - _DIVIDEND = 59 - _DIVISOR = 7 - _QUOTIENT = 8 - _REMAINDER = 3 - - _REQUEST = math_pb2.DivArgs(dividend=_DIVIDEND, divisor=_DIVISOR) - _RESPONSE = math_pb2.DivReply(quotient=_QUOTIENT, remainder=_REMAINDER) - - def method(self): - return 'Div' - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, request_bytestring): - return math_pb2.DivArgs.FromString(request_bytestring) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, response_bytestring): - return math_pb2.DivReply.FromString(response_bytestring) - - def requests(self): - return [self._REQUEST] - - def response_for_request(self, request): - return self._RESPONSE - - def verify_requests(self, experimental_requests): - return tuple(experimental_requests) == (self._REQUEST,) - - def verify_responses(self, experimental_responses): - return tuple(experimental_responses) == (self._RESPONSE,) - - -class BidirectionallyStreamingScenario(ProtoScenario): - """A scenario that transmits no protocol buffers in either direction.""" - - _STREAM_LENGTH = 200 - _REQUESTS = tuple( - math_pb2.DivArgs(dividend=59 + index, divisor=7 + index) - for index in range(_STREAM_LENGTH)) - - def __init__(self): - self._lock = threading.Lock() - self._responses = [] - - def method(self): - return 'DivMany' - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, request_bytestring): - return math_pb2.DivArgs.FromString(request_bytestring) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, response_bytestring): - return math_pb2.DivReply.FromString(response_bytestring) - - def requests(self): - return self._REQUESTS - - def response_for_request(self, request): - quotient, remainder = divmod(request.dividend, request.divisor) - response = math_pb2.DivReply(quotient=quotient, remainder=remainder) - with self._lock: - self._responses.append(response) - return response - - def verify_requests(self, experimental_requests): - return tuple(experimental_requests) == self._REQUESTS - - def verify_responses(self, experimental_responses): - with self._lock: - return tuple(experimental_responses) == tuple(self._responses) diff --git a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py index ae8de523ec..3c00f686ce 100644 --- a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py +++ b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py @@ -104,7 +104,7 @@ class ChannelConnectivityTest(unittest.TestCase): grpc.ChannelConnectivity.READY, fifth_connectivities) def test_immediately_connectable_channel_connectivity(self): - server = _server.Server((), futures.ThreadPoolExecutor(max_workers=0)) + server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ()) port = server.add_insecure_port('[::]:0') server.start() first_callback = _Callback() @@ -143,7 +143,7 @@ class ChannelConnectivityTest(unittest.TestCase): grpc.ChannelConnectivity.SHUTDOWN, fourth_connectivities) def test_reachable_then_unreachable_channel_connectivity(self): - server = _server.Server((), futures.ThreadPoolExecutor(max_workers=0)) + server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ()) port = server.add_insecure_port('[::]:0') server.start() callback = _Callback() diff --git a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py index b84bc0197a..e8982ed2de 100644 --- a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py +++ b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py @@ -78,7 +78,7 @@ class ChannelReadyFutureTest(unittest.TestCase): self.assertFalse(ready_future.running()) def test_immediately_connectable_channel_connectivity(self): - server = _server.Server((), futures.ThreadPoolExecutor(max_workers=0)) + server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ()) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:{}'.format(port)) diff --git a/src/python/grpcio_tests/tests/unit/_compression_test.py b/src/python/grpcio_tests/tests/unit/_compression_test.py index 9e8b8578c1..83b9109466 100644 --- a/src/python/grpcio_tests/tests/unit/_compression_test.py +++ b/src/python/grpcio_tests/tests/unit/_compression_test.py @@ -88,7 +88,8 @@ class CompressionTest(unittest.TestCase): def setUp(self): self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server((_GenericHandler(),), self._server_pool) + self._server = grpc.server( + self._server_pool, handlers=(_GenericHandler(),)) self._port = self._server.add_insecure_port('[::]:0') self._server.start() diff --git a/src/python/grpcio_tests/tests/unit/_credentials_test.py b/src/python/grpcio_tests/tests/unit/_credentials_test.py new file mode 100644 index 0000000000..87af85a0b9 --- /dev/null +++ b/src/python/grpcio_tests/tests/unit/_credentials_test.py @@ -0,0 +1,72 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Tests of credentials.""" + +import unittest + +import grpc + + +class CredentialsTest(unittest.TestCase): + + def test_call_credentials_composition(self): + first = grpc.access_token_call_credentials('abc') + second = grpc.access_token_call_credentials('def') + third = grpc.access_token_call_credentials('ghi') + + first_and_second = grpc.composite_call_credentials(first, second) + first_second_and_third = grpc.composite_call_credentials( + first, second, third) + + self.assertIsInstance(first_and_second, grpc.CallCredentials) + self.assertIsInstance(first_second_and_third, grpc.CallCredentials) + + def test_channel_credentials_composition(self): + first_call_credentials = grpc.access_token_call_credentials('abc') + second_call_credentials = grpc.access_token_call_credentials('def') + third_call_credentials = grpc.access_token_call_credentials('ghi') + channel_credentials = grpc.ssl_channel_credentials() + + channel_and_first = grpc.composite_channel_credentials( + channel_credentials, first_call_credentials) + channel_first_and_second = grpc.composite_channel_credentials( + channel_credentials, first_call_credentials, second_call_credentials) + channel_first_second_and_third = grpc.composite_channel_credentials( + channel_credentials, first_call_credentials, second_call_credentials, + third_call_credentials) + + self.assertIsInstance(channel_and_first, grpc.ChannelCredentials) + self.assertIsInstance(channel_first_and_second, grpc.ChannelCredentials) + self.assertIsInstance( + channel_first_second_and_third, grpc.ChannelCredentials) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py index cac0c8b3b9..cf212c5653 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py @@ -81,11 +81,11 @@ class _Handler(object): self._state.condition.wait() with self._lock: - self._call.start_batch( + self._call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), _RECEIVE_CLOSE_ON_SERVER_TAG) - self._call.start_batch( + self._call.start_server_batch( cygrpc.Operations((cygrpc.operation_receive_message(_EMPTY_FLAGS),)), _RECEIVE_MESSAGE_TAG) first_event = self._completion_queue.poll() @@ -101,7 +101,7 @@ class _Handler(object): _EMPTY_METADATA, cygrpc.StatusCode.ok, b'test details!', _EMPTY_FLAGS), ) - self._call.start_batch( + self._call.start_server_batch( cygrpc.Operations(operations), _SERVER_COMPLETE_CALL_TAG) self._completion_queue.poll() self._completion_queue.poll() @@ -193,7 +193,7 @@ class CancelManyCallsTest(unittest.TestCase): cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), ) tag = 'client_complete_call_{0:04d}_tag'.format(index) - client_call.start_batch(cygrpc.Operations(operations), tag) + client_call.start_client_batch(cygrpc.Operations(operations), tag) client_due.add(tag) client_calls.append(client_call) diff --git a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py index 27fcee0d6f..152d8edde3 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py @@ -168,12 +168,12 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase): client_complete_rpc_tag = 'client_complete_rpc_tag' with client_condition: client_receive_initial_metadata_start_batch_result = ( - client_call.start_batch(cygrpc.Operations([ + client_call.start_client_batch(cygrpc.Operations([ cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), ]), client_receive_initial_metadata_tag)) client_due.add(client_receive_initial_metadata_tag) client_complete_rpc_start_batch_result = ( - client_call.start_batch(cygrpc.Operations([ + client_call.start_client_batch(cygrpc.Operations([ cygrpc.operation_send_initial_metadata( _EMPTY_METADATA, _EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), @@ -185,30 +185,30 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase): with server_call_condition: server_send_initial_metadata_start_batch_result = ( - server_rpc_event.operation_call.start_batch(cygrpc.Operations([ + server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_send_initial_metadata( _EMPTY_METADATA, _EMPTY_FLAGS), - ]), server_send_initial_metadata_tag)) + ], server_send_initial_metadata_tag)) server_send_first_message_start_batch_result = ( - server_rpc_event.operation_call.start_batch(cygrpc.Operations([ + server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), - ]), server_send_first_message_tag)) + ], server_send_first_message_tag)) server_send_initial_metadata_event = server_call_driver.event_with_tag( server_send_initial_metadata_tag) server_send_first_message_event = server_call_driver.event_with_tag( server_send_first_message_tag) with server_call_condition: server_send_second_message_start_batch_result = ( - server_rpc_event.operation_call.start_batch(cygrpc.Operations([ + server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), - ]), server_send_second_message_tag)) + ], server_send_second_message_tag)) server_complete_rpc_start_batch_result = ( - server_rpc_event.operation_call.start_batch(cygrpc.Operations([ + server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_send_status_from_server( cygrpc.Metadata(()), cygrpc.StatusCode.ok, b'test details', _EMPTY_FLAGS), - ]), server_complete_rpc_tag)) + ], server_complete_rpc_tag)) server_send_second_message_event = server_call_driver.event_with_tag( server_send_second_message_tag) server_complete_rpc_event = server_call_driver.event_with_tag( @@ -218,7 +218,7 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase): with client_condition: client_receive_first_message_tag = 'client_receive_first_message_tag' client_receive_first_message_start_batch_result = ( - client_call.start_batch(cygrpc.Operations([ + client_call.start_client_batch(cygrpc.Operations([ cygrpc.operation_receive_message(_EMPTY_FLAGS), ]), client_receive_first_message_tag)) client_due.add(client_receive_first_message_tag) diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py index b740695e35..f9a8e2401b 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py @@ -186,7 +186,8 @@ class ServerClientMixin(object): def performer(): tag = object() try: - call_result = call.start_batch(cygrpc.Operations(operations), tag) + call_result = call.start_client_batch( + cygrpc.Operations(operations), tag) self.assertEqual(cygrpc.CallError.ok, call_result) event = queue.poll(deadline) self.assertEqual(cygrpc.CompletionType.operation_complete, event.type) @@ -231,7 +232,7 @@ class ServerClientMixin(object): cygrpc.Metadatum(CLIENT_METADATA_ASCII_KEY, CLIENT_METADATA_ASCII_VALUE), cygrpc.Metadatum(CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE)]) - client_start_batch_result = client_call.start_batch(cygrpc.Operations([ + client_start_batch_result = client_call.start_client_batch([ cygrpc.operation_send_initial_metadata(client_initial_metadata, _EMPTY_FLAGS), cygrpc.operation_send_message(REQUEST, _EMPTY_FLAGS), @@ -239,7 +240,7 @@ class ServerClientMixin(object): cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS) - ]), client_call_tag) + ], client_call_tag) self.assertEqual(cygrpc.CallError.ok, client_start_batch_result) client_event_future = test_utilities.CompletionQueuePollFuture( self.client_completion_queue, cygrpc_deadline) @@ -268,7 +269,7 @@ class ServerClientMixin(object): server_trailing_metadata = cygrpc.Metadata([ cygrpc.Metadatum(SERVER_TRAILING_METADATA_KEY, SERVER_TRAILING_METADATA_VALUE)]) - server_start_batch_result = server_call.start_batch([ + server_start_batch_result = server_call.start_server_batch([ cygrpc.operation_send_initial_metadata(server_initial_metadata, _EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), @@ -280,8 +281,8 @@ class ServerClientMixin(object): ], server_call_tag) self.assertEqual(cygrpc.CallError.ok, server_start_batch_result) - client_event = client_event_future.result() server_event = self.server_completion_queue.poll(cygrpc_deadline) + client_event = client_event_future.result() self.assertEqual(6, len(client_event.batch_operations)) found_client_op_types = set() diff --git a/src/python/grpcio_tests/tests/unit/_empty_message_test.py b/src/python/grpcio_tests/tests/unit/_empty_message_test.py index 8c7d697728..131f6e9452 100644 --- a/src/python/grpcio_tests/tests/unit/_empty_message_test.py +++ b/src/python/grpcio_tests/tests/unit/_empty_message_test.py @@ -103,7 +103,8 @@ class EmptyMessageTest(unittest.TestCase): def setUp(self): self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server((_GenericHandler(),), self._server_pool) + self._server = grpc.server( + self._server_pool, handlers=(_GenericHandler(),)) port = self._server.add_insecure_port('[::]:0') self._server.start() self._channel = grpc.insecure_channel('localhost:%d' % port) diff --git a/src/python/grpcio_tests/tests/unit/_exit_scenarios.py b/src/python/grpcio_tests/tests/unit/_exit_scenarios.py index 24a2faef85..b33802bf57 100644 --- a/src/python/grpcio_tests/tests/unit/_exit_scenarios.py +++ b/src/python/grpcio_tests/tests/unit/_exit_scenarios.py @@ -184,11 +184,11 @@ if __name__ == '__main__': args = parser.parse_args() if args.scenario == UNSTARTED_SERVER: - server = grpc.server((), DaemonPool()) + server = grpc.server(DaemonPool()) if args.wait_for_interrupt: time.sleep(WAIT_TIME) elif args.scenario == RUNNING_SERVER: - server = grpc.server((), DaemonPool()) + server = grpc.server(DaemonPool()) port = server.add_insecure_port('[::]:0') server.start() if args.wait_for_interrupt: @@ -203,7 +203,7 @@ if __name__ == '__main__': if args.wait_for_interrupt: time.sleep(WAIT_TIME) elif args.scenario == POLL_CONNECTIVITY: - server = grpc.server((), DaemonPool()) + server = grpc.server(DaemonPool()) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:%d' % port) @@ -217,7 +217,7 @@ if __name__ == '__main__': else: handler = GenericHandler() - server = grpc.server((), DaemonPool()) + server = grpc.server(DaemonPool()) port = server.add_insecure_port('[::]:0') server.add_generic_rpc_handlers((handler,)) server.start() diff --git a/src/python/grpcio_tests/tests/unit/_junkdrawer/math_pb2.py b/src/python/grpcio_tests/tests/unit/_junkdrawer/math_pb2.py deleted file mode 100644 index 20165955b4..0000000000 --- a/src/python/grpcio_tests/tests/unit/_junkdrawer/math_pb2.py +++ /dev/null @@ -1,266 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# TODO(nathaniel): Remove this from source control after having made -# generation from the math.proto source part of GRPC's build-and-test -# process. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: math.proto - -import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -from google.protobuf import descriptor_pb2 -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='math.proto', - package='math', - serialized_pb=_b('\n\nmath.proto\x12\x04math\",\n\x07\x44ivArgs\x12\x10\n\x08\x64ividend\x18\x01 \x02(\x03\x12\x0f\n\x07\x64ivisor\x18\x02 \x02(\x03\"/\n\x08\x44ivReply\x12\x10\n\x08quotient\x18\x01 \x02(\x03\x12\x11\n\tremainder\x18\x02 \x02(\x03\"\x18\n\x07\x46ibArgs\x12\r\n\x05limit\x18\x01 \x01(\x03\"\x12\n\x03Num\x12\x0b\n\x03num\x18\x01 \x02(\x03\"\x19\n\x08\x46ibReply\x12\r\n\x05\x63ount\x18\x01 \x02(\x03\x32\xa4\x01\n\x04Math\x12&\n\x03\x44iv\x12\r.math.DivArgs\x1a\x0e.math.DivReply\"\x00\x12.\n\x07\x44ivMany\x12\r.math.DivArgs\x1a\x0e.math.DivReply\"\x00(\x01\x30\x01\x12#\n\x03\x46ib\x12\r.math.FibArgs\x1a\t.math.Num\"\x00\x30\x01\x12\x1f\n\x03Sum\x12\t.math.Num\x1a\t.math.Num\"\x00(\x01') -) -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - - - - -_DIVARGS = _descriptor.Descriptor( - name='DivArgs', - full_name='math.DivArgs', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='dividend', full_name='math.DivArgs.dividend', index=0, - number=1, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - _descriptor.FieldDescriptor( - name='divisor', full_name='math.DivArgs.divisor', index=1, - number=2, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - oneofs=[ - ], - serialized_start=20, - serialized_end=64, -) - - -_DIVREPLY = _descriptor.Descriptor( - name='DivReply', - full_name='math.DivReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='quotient', full_name='math.DivReply.quotient', index=0, - number=1, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - _descriptor.FieldDescriptor( - name='remainder', full_name='math.DivReply.remainder', index=1, - number=2, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - oneofs=[ - ], - serialized_start=66, - serialized_end=113, -) - - -_FIBARGS = _descriptor.Descriptor( - name='FibArgs', - full_name='math.FibArgs', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='limit', full_name='math.FibArgs.limit', index=0, - number=1, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - oneofs=[ - ], - serialized_start=115, - serialized_end=139, -) - - -_NUM = _descriptor.Descriptor( - name='Num', - full_name='math.Num', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='num', full_name='math.Num.num', index=0, - number=1, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - oneofs=[ - ], - serialized_start=141, - serialized_end=159, -) - - -_FIBREPLY = _descriptor.Descriptor( - name='FibReply', - full_name='math.FibReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='count', full_name='math.FibReply.count', index=0, - number=1, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - oneofs=[ - ], - serialized_start=161, - serialized_end=186, -) - -DESCRIPTOR.message_types_by_name['DivArgs'] = _DIVARGS -DESCRIPTOR.message_types_by_name['DivReply'] = _DIVREPLY -DESCRIPTOR.message_types_by_name['FibArgs'] = _FIBARGS -DESCRIPTOR.message_types_by_name['Num'] = _NUM -DESCRIPTOR.message_types_by_name['FibReply'] = _FIBREPLY - -DivArgs = _reflection.GeneratedProtocolMessageType('DivArgs', (_message.Message,), dict( - DESCRIPTOR = _DIVARGS, - __module__ = 'math_pb2' - # @@protoc_insertion_point(class_scope:math.DivArgs) - )) -_sym_db.RegisterMessage(DivArgs) - -DivReply = _reflection.GeneratedProtocolMessageType('DivReply', (_message.Message,), dict( - DESCRIPTOR = _DIVREPLY, - __module__ = 'math_pb2' - # @@protoc_insertion_point(class_scope:math.DivReply) - )) -_sym_db.RegisterMessage(DivReply) - -FibArgs = _reflection.GeneratedProtocolMessageType('FibArgs', (_message.Message,), dict( - DESCRIPTOR = _FIBARGS, - __module__ = 'math_pb2' - # @@protoc_insertion_point(class_scope:math.FibArgs) - )) -_sym_db.RegisterMessage(FibArgs) - -Num = _reflection.GeneratedProtocolMessageType('Num', (_message.Message,), dict( - DESCRIPTOR = _NUM, - __module__ = 'math_pb2' - # @@protoc_insertion_point(class_scope:math.Num) - )) -_sym_db.RegisterMessage(Num) - -FibReply = _reflection.GeneratedProtocolMessageType('FibReply', (_message.Message,), dict( - DESCRIPTOR = _FIBREPLY, - __module__ = 'math_pb2' - # @@protoc_insertion_point(class_scope:math.FibReply) - )) -_sym_db.RegisterMessage(FibReply) - - -# @@protoc_insertion_point(module_scope) diff --git a/src/python/grpcio_tests/tests/unit/_links/__init__.py b/src/python/grpcio_tests/tests/unit/_links/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_tests/tests/unit/_links/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_tests/tests/unit/_links/_proto_scenarios.py b/src/python/grpcio_tests/tests/unit/_links/_proto_scenarios.py deleted file mode 100644 index 50661085f9..0000000000 --- a/src/python/grpcio_tests/tests/unit/_links/_proto_scenarios.py +++ /dev/null @@ -1,262 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Test scenarios using protocol buffers.""" - -import abc -import threading - -import six - -from tests.unit._junkdrawer import math_pb2 -from tests.unit.framework.common import test_constants - - -class ProtoScenario(six.with_metaclass(abc.ABCMeta)): - """An RPC test scenario using protocol buffers.""" - - @abc.abstractmethod - def group_and_method(self): - """Access the test group and method. - - Returns: - The test group and method as a pair. - """ - raise NotImplementedError() - - @abc.abstractmethod - def serialize_request(self, request): - """Serialize a request protocol buffer. - - Args: - request: A request protocol buffer. - - Returns: - The bytestring serialization of the given request protocol buffer. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_request(self, request_bytestring): - """Deserialize a request protocol buffer. - - Args: - request_bytestring: The bytestring serialization of a request protocol - buffer. - - Returns: - The request protocol buffer deserialized from the given byte string. - """ - raise NotImplementedError() - - @abc.abstractmethod - def serialize_response(self, response): - """Serialize a response protocol buffer. - - Args: - response: A response protocol buffer. - - Returns: - The bytestring serialization of the given response protocol buffer. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_response(self, response_bytestring): - """Deserialize a response protocol buffer. - - Args: - response_bytestring: The bytestring serialization of a response protocol - buffer. - - Returns: - The response protocol buffer deserialized from the given byte string. - """ - raise NotImplementedError() - - @abc.abstractmethod - def requests(self): - """Access the sequence of requests for this scenario. - - Returns: - A sequence of request protocol buffers. - """ - raise NotImplementedError() - - @abc.abstractmethod - def response_for_request(self, request): - """Access the response for a particular request. - - Args: - request: A request protocol buffer. - - Returns: - The response protocol buffer appropriate for the given request. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify_requests(self, experimental_requests): - """Verify the requests transmitted through the system under test. - - Args: - experimental_requests: The request protocol buffers transmitted through - the system under test. - - Returns: - True if the requests satisfy this test scenario; False otherwise. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify_responses(self, experimental_responses): - """Verify the responses transmitted through the system under test. - - Args: - experimental_responses: The response protocol buffers transmitted through - the system under test. - - Returns: - True if the responses satisfy this test scenario; False otherwise. - """ - raise NotImplementedError() - - -class EmptyScenario(ProtoScenario): - """A scenario that transmits no protocol buffers in either direction.""" - - def group_and_method(self): - return 'math.Math', 'DivMany' - - def serialize_request(self, request): - raise ValueError('This should not be necessary to call!') - - def deserialize_request(self, request_bytestring): - raise ValueError('This should not be necessary to call!') - - def serialize_response(self, response): - raise ValueError('This should not be necessary to call!') - - def deserialize_response(self, response_bytestring): - raise ValueError('This should not be necessary to call!') - - def requests(self): - return () - - def response_for_request(self, request): - raise ValueError('This should not be necessary to call!') - - def verify_requests(self, experimental_requests): - return not experimental_requests - - def verify_responses(self, experimental_responses): - return not experimental_responses - - -class BidirectionallyUnaryScenario(ProtoScenario): - """A scenario that transmits no protocol buffers in either direction.""" - - _DIVIDEND = 59 - _DIVISOR = 7 - _QUOTIENT = 8 - _REMAINDER = 3 - - _REQUEST = math_pb2.DivArgs(dividend=_DIVIDEND, divisor=_DIVISOR) - _RESPONSE = math_pb2.DivReply(quotient=_QUOTIENT, remainder=_REMAINDER) - - def group_and_method(self): - return 'math.Math', 'Div' - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, request_bytestring): - return math_pb2.DivArgs.FromString(request_bytestring) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, response_bytestring): - return math_pb2.DivReply.FromString(response_bytestring) - - def requests(self): - return [self._REQUEST] - - def response_for_request(self, request): - return self._RESPONSE - - def verify_requests(self, experimental_requests): - return tuple(experimental_requests) == (self._REQUEST,) - - def verify_responses(self, experimental_responses): - return tuple(experimental_responses) == (self._RESPONSE,) - - -class BidirectionallyStreamingScenario(ProtoScenario): - """A scenario that transmits no protocol buffers in either direction.""" - - _REQUESTS = tuple( - math_pb2.DivArgs(dividend=59 + index, divisor=7 + index) - for index in range(test_constants.STREAM_LENGTH)) - - def __init__(self): - self._lock = threading.Lock() - self._responses = [] - - def group_and_method(self): - return 'math.Math', 'DivMany' - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, request_bytestring): - return math_pb2.DivArgs.FromString(request_bytestring) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, response_bytestring): - return math_pb2.DivReply.FromString(response_bytestring) - - def requests(self): - return self._REQUESTS - - def response_for_request(self, request): - quotient, remainder = divmod(request.dividend, request.divisor) - response = math_pb2.DivReply(quotient=quotient, remainder=remainder) - with self._lock: - self._responses.append(response) - return response - - def verify_requests(self, experimental_requests): - return tuple(experimental_requests) == self._REQUESTS - - def verify_responses(self, experimental_responses): - with self._lock: - return tuple(experimental_responses) == tuple(self._responses) diff --git a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py index 0fd02d2a22..fb3e547781 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py @@ -189,7 +189,7 @@ class MetadataCodeDetailsTest(unittest.TestCase): self._servicer = _Servicer() self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server( - (_generic_handler(self._servicer),), self._server_pool) + self._server_pool, handlers=(_generic_handler(self._servicer),)) port = self._server.add_insecure_port('[::]:0') self._server.start() diff --git a/src/python/grpcio_tests/tests/unit/_metadata_test.py b/src/python/grpcio_tests/tests/unit/_metadata_test.py index c637a28039..da73476929 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_test.py @@ -161,8 +161,8 @@ class MetadataTest(unittest.TestCase): def setUp(self): self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server((_GenericHandler(weakref.proxy(self)),), - self._server_pool) + self._server = grpc.server( + self._server_pool, handlers=(_GenericHandler(weakref.proxy(self)),)) port = self._server.add_insecure_port('[::]:0') self._server.start() self._channel = grpc.insecure_channel('localhost:%d' % port, diff --git a/src/python/grpcio_tests/tests/unit/_rpc_test.py b/src/python/grpcio_tests/tests/unit/_rpc_test.py index c70d65a6df..59bf240d28 100644 --- a/src/python/grpcio_tests/tests/unit/_rpc_test.py +++ b/src/python/grpcio_tests/tests/unit/_rpc_test.py @@ -184,7 +184,7 @@ class RPCTest(unittest.TestCase): self._handler = _Handler(self._control) self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server((), self._server_pool) + self._server = grpc.server(self._server_pool) port = self._server.add_insecure_port('[::]:0') self._server.add_generic_rpc_handlers((_GenericHandler(self._handler),)) self._server.start() diff --git a/src/python/grpcio_tests/tests/unit/framework/core/__init__.py b/src/python/grpcio_tests/tests/unit/framework/core/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/core/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/__init__.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/base/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_control.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_control.py deleted file mode 100644 index 0eb38abf22..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_control.py +++ /dev/null @@ -1,570 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Part of the tests of the base interface of RPC Framework.""" - -from __future__ import division - -import abc -import collections -import enum -import random # pylint: disable=unused-import -import threading -import time - -import six - -from grpc.framework.interfaces.base import base -from tests.unit.framework.common import test_constants -from tests.unit.framework.interfaces.base import _sequence -from tests.unit.framework.interfaces.base import _state -from tests.unit.framework.interfaces.base import test_interfaces # pylint: disable=unused-import - -_GROUP = 'base test cases test group' -_METHOD = 'base test cases test method' - -_PAYLOAD_RANDOM_SECTION_MAXIMUM_SIZE = test_constants.PAYLOAD_SIZE // 20 -_MINIMUM_PAYLOAD_SIZE = test_constants.PAYLOAD_SIZE // 600 - - -def _create_payload(randomness): - length = randomness.randint( - _MINIMUM_PAYLOAD_SIZE, test_constants.PAYLOAD_SIZE) - random_section_length = randomness.randint( - 0, min(_PAYLOAD_RANDOM_SECTION_MAXIMUM_SIZE, length)) - random_section = bytes( - bytearray( - randomness.getrandbits(8) for _ in range(random_section_length))) - sevens_section = b'\x07' * (length - random_section_length) - return b''.join(randomness.sample((random_section, sevens_section), 2)) - - -def _anything_in_flight(state): - return ( - state.invocation_initial_metadata_in_flight is not None or - state.invocation_payloads_in_flight or - state.invocation_completion_in_flight is not None or - state.service_initial_metadata_in_flight is not None or - state.service_payloads_in_flight or - state.service_completion_in_flight is not None or - 0 < state.invocation_allowance_in_flight or - 0 < state.service_allowance_in_flight - ) - - -def _verify_service_advance_and_update_state( - initial_metadata, payload, completion, allowance, state, implementation): - if initial_metadata is not None: - if state.invocation_initial_metadata_received: - return 'Later invocation initial metadata received: %s' % ( - initial_metadata,) - if state.invocation_payloads_received: - return 'Invocation initial metadata received after payloads: %s' % ( - state.invocation_payloads_received) - if state.invocation_completion_received: - return 'Invocation initial metadata received after invocation completion!' - if not implementation.metadata_transmitted( - state.invocation_initial_metadata_in_flight, initial_metadata): - return 'Invocation initial metadata maltransmitted: %s, %s' % ( - state.invocation_initial_metadata_in_flight, initial_metadata) - else: - state.invocation_initial_metadata_in_flight = None - state.invocation_initial_metadata_received = True - - if payload is not None: - if state.invocation_completion_received: - return 'Invocation payload received after invocation completion!' - elif not state.invocation_payloads_in_flight: - return 'Invocation payload "%s" received but not in flight!' % (payload,) - elif state.invocation_payloads_in_flight[0] != payload: - return 'Invocation payload mismatch: %s, %s' % ( - state.invocation_payloads_in_flight[0], payload) - elif state.service_side_invocation_allowance < 1: - return 'Disallowed invocation payload!' - else: - state.invocation_payloads_in_flight.pop(0) - state.invocation_payloads_received += 1 - state.service_side_invocation_allowance -= 1 - - if completion is not None: - if state.invocation_completion_received: - return 'Later invocation completion received: %s' % (completion,) - elif not implementation.completion_transmitted( - state.invocation_completion_in_flight, completion): - return 'Invocation completion maltransmitted: %s, %s' % ( - state.invocation_completion_in_flight, completion) - else: - state.invocation_completion_in_flight = None - state.invocation_completion_received = True - - if allowance is not None: - if allowance <= 0: - return 'Illegal allowance value: %s' % (allowance,) - else: - state.service_allowance_in_flight -= allowance - state.service_side_service_allowance += allowance - - -def _verify_invocation_advance_and_update_state( - initial_metadata, payload, completion, allowance, state, implementation): - if initial_metadata is not None: - if state.service_initial_metadata_received: - return 'Later service initial metadata received: %s' % (initial_metadata,) - if state.service_payloads_received: - return 'Service initial metadata received after service payloads: %s' % ( - state.service_payloads_received) - if state.service_completion_received: - return 'Service initial metadata received after service completion!' - if not implementation.metadata_transmitted( - state.service_initial_metadata_in_flight, initial_metadata): - return 'Service initial metadata maltransmitted: %s, %s' % ( - state.service_initial_metadata_in_flight, initial_metadata) - else: - state.service_initial_metadata_in_flight = None - state.service_initial_metadata_received = True - - if payload is not None: - if state.service_completion_received: - return 'Service payload received after service completion!' - elif not state.service_payloads_in_flight: - return 'Service payload "%s" received but not in flight!' % (payload,) - elif state.service_payloads_in_flight[0] != payload: - return 'Service payload mismatch: %s, %s' % ( - state.invocation_payloads_in_flight[0], payload) - elif state.invocation_side_service_allowance < 1: - return 'Disallowed service payload!' - else: - state.service_payloads_in_flight.pop(0) - state.service_payloads_received += 1 - state.invocation_side_service_allowance -= 1 - - if completion is not None: - if state.service_completion_received: - return 'Later service completion received: %s' % (completion,) - elif not implementation.completion_transmitted( - state.service_completion_in_flight, completion): - return 'Service completion maltransmitted: %s, %s' % ( - state.service_completion_in_flight, completion) - else: - state.service_completion_in_flight = None - state.service_completion_received = True - - if allowance is not None: - if allowance <= 0: - return 'Illegal allowance value: %s' % (allowance,) - else: - state.invocation_allowance_in_flight -= allowance - state.invocation_side_service_allowance += allowance - - -class Invocation( - collections.namedtuple( - 'Invocation', - ('group', 'method', 'subscription_kind', 'timeout', 'initial_metadata', - 'payload', 'completion',))): - """A description of operation invocation. - - Attributes: - group: The group identifier for the operation. - method: The method identifier for the operation. - subscription_kind: A base.Subscription.Kind value describing the kind of - subscription to use for the operation. - timeout: A duration in seconds to pass as the timeout value for the - operation. - initial_metadata: An object to pass as the initial metadata for the - operation or None. - payload: An object to pass as a payload value for the operation or None. - completion: An object to pass as a completion value for the operation or - None. - """ - - -class OnAdvance( - collections.namedtuple( - 'OnAdvance', - ('kind', 'initial_metadata', 'payload', 'completion', 'allowance'))): - """Describes action to be taken in a test in response to an advance call. - - Attributes: - kind: A Kind value describing the overall kind of response. - initial_metadata: An initial metadata value to pass to a call of the advance - method of the operator under test. Only valid if kind is Kind.ADVANCE and - may be None. - payload: A payload value to pass to a call of the advance method of the - operator under test. Only valid if kind is Kind.ADVANCE and may be None. - completion: A base.Completion value to pass to a call of the advance method - of the operator under test. Only valid if kind is Kind.ADVANCE and may be - None. - allowance: An allowance value to pass to a call of the advance method of the - operator under test. Only valid if kind is Kind.ADVANCE and may be None. - """ - - @enum.unique - class Kind(enum.Enum): - ADVANCE = 'advance' - DEFECT = 'defect' - IDLE = 'idle' - - -_DEFECT_ON_ADVANCE = OnAdvance(OnAdvance.Kind.DEFECT, None, None, None, None) -_IDLE_ON_ADVANCE = OnAdvance(OnAdvance.Kind.IDLE, None, None, None, None) - - -class Instruction( - collections.namedtuple( - 'Instruction', - ('kind', 'advance_args', 'advance_kwargs', 'conclude_success', - 'conclude_message', 'conclude_invocation_outcome_kind', - 'conclude_service_outcome_kind',))): - """""" - - @enum.unique - class Kind(enum.Enum): - ADVANCE = 'ADVANCE' - CANCEL = 'CANCEL' - CONCLUDE = 'CONCLUDE' - - -class Controller(six.with_metaclass(abc.ABCMeta)): - - @abc.abstractmethod - def failed(self, message): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def serialize_request(self, request): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_request(self, serialized_request): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def serialize_response(self, response): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_response(self, serialized_response): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def invocation(self): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def poll(self): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def on_service_advance( - self, initial_metadata, payload, completion, allowance): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def on_invocation_advance( - self, initial_metadata, payload, completion, allowance): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def service_on_termination(self, outcome): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def invocation_on_termination(self, outcome): - """""" - raise NotImplementedError() - - -class ControllerCreator(six.with_metaclass(abc.ABCMeta)): - - @abc.abstractmethod - def name(self): - """""" - raise NotImplementedError() - - @abc.abstractmethod - def controller(self, implementation, randomness): - """""" - raise NotImplementedError() - - -class _Remainder( - collections.namedtuple( - '_Remainder', - ('invocation_payloads', 'service_payloads', 'invocation_completion', - 'service_completion',))): - """Describes work remaining to be done in a portion of a test. - - Attributes: - invocation_payloads: The number of payloads to be sent from the invocation - side of the operation to the service side of the operation. - service_payloads: The number of payloads to be sent from the service side of - the operation to the invocation side of the operation. - invocation_completion: Whether or not completion from the invocation side of - the operation should be indicated and has yet to be indicated. - service_completion: Whether or not completion from the service side of the - operation should be indicated and has yet to be indicated. - """ - - -class _SequenceController(Controller): - - def __init__(self, sequence, implementation, randomness): - """Constructor. - - Args: - sequence: A _sequence.Sequence describing the steps to be taken in the - test at a relatively high level. - implementation: A test_interfaces.Implementation encapsulating the - base interface implementation that is the system under test. - randomness: A random.Random instance for use in the test. - """ - self._condition = threading.Condition() - self._sequence = sequence - self._implementation = implementation - self._randomness = randomness - - self._until = None - self._remaining_elements = None - self._poll_next = None - self._message = None - - self._state = _state.OperationState() - self._todo = None - - # called with self._condition - def _failed(self, message): - self._message = message - self._condition.notify_all() - - def _passed(self, invocation_outcome, service_outcome): - self._poll_next = Instruction( - Instruction.Kind.CONCLUDE, None, None, True, None, invocation_outcome, - service_outcome) - self._condition.notify_all() - - def failed(self, message): - with self._condition: - self._failed(message) - - def serialize_request(self, request): - return request + request - - def deserialize_request(self, serialized_request): - return serialized_request[:len(serialized_request) // 2] - - def serialize_response(self, response): - return response * 3 - - def deserialize_response(self, serialized_response): - return serialized_response[2 * len(serialized_response) // 3:] - - def invocation(self): - with self._condition: - self._until = time.time() + self._sequence.maximum_duration - self._remaining_elements = list(self._sequence.elements) - if self._sequence.invocation.initial_metadata: - initial_metadata = self._implementation.invocation_initial_metadata() - self._state.invocation_initial_metadata_in_flight = initial_metadata - else: - initial_metadata = None - if self._sequence.invocation.payload: - payload = _create_payload(self._randomness) - self._state.invocation_payloads_in_flight.append(payload) - else: - payload = None - if self._sequence.invocation.complete: - completion = self._implementation.invocation_completion() - self._state.invocation_completion_in_flight = completion - else: - completion = None - return Invocation( - _GROUP, _METHOD, base.Subscription.Kind.FULL, - self._sequence.invocation.timeout, initial_metadata, payload, - completion) - - def poll(self): - with self._condition: - while True: - if self._message is not None: - return Instruction( - Instruction.Kind.CONCLUDE, None, None, False, self._message, None, - None) - elif self._poll_next: - poll_next = self._poll_next - self._poll_next = None - return poll_next - elif self._until < time.time(): - return Instruction( - Instruction.Kind.CONCLUDE, None, None, False, - 'overran allotted time!', None, None) - else: - self._condition.wait(timeout=self._until-time.time()) - - def on_service_advance( - self, initial_metadata, payload, completion, allowance): - with self._condition: - message = _verify_service_advance_and_update_state( - initial_metadata, payload, completion, allowance, self._state, - self._implementation) - if message is not None: - self._failed(message) - if self._todo is not None: - raise ValueError('TODO!!!') - elif _anything_in_flight(self._state): - return _IDLE_ON_ADVANCE - elif self._remaining_elements: - element = self._remaining_elements.pop(0) - if element.kind is _sequence.Element.Kind.SERVICE_TRANSMISSION: - if element.transmission.initial_metadata: - initial_metadata = self._implementation.service_initial_metadata() - self._state.service_initial_metadata_in_flight = initial_metadata - else: - initial_metadata = None - if element.transmission.payload: - payload = _create_payload(self._randomness) - self._state.service_payloads_in_flight.append(payload) - self._state.service_side_service_allowance -= 1 - else: - payload = None - if element.transmission.complete: - completion = self._implementation.service_completion() - self._state.service_completion_in_flight = completion - else: - completion = None - if (not self._state.invocation_completion_received and - 0 <= self._state.service_side_invocation_allowance): - allowance = 1 - self._state.service_side_invocation_allowance += 1 - self._state.invocation_allowance_in_flight += 1 - else: - allowance = None - return OnAdvance( - OnAdvance.Kind.ADVANCE, initial_metadata, payload, completion, - allowance) - else: - raise ValueError('TODO!!!') - else: - return _IDLE_ON_ADVANCE - - def on_invocation_advance( - self, initial_metadata, payload, completion, allowance): - with self._condition: - message = _verify_invocation_advance_and_update_state( - initial_metadata, payload, completion, allowance, self._state, - self._implementation) - if message is not None: - self._failed(message) - if self._todo is not None: - raise ValueError('TODO!!!') - elif _anything_in_flight(self._state): - return _IDLE_ON_ADVANCE - elif self._remaining_elements: - element = self._remaining_elements.pop(0) - if element.kind is _sequence.Element.Kind.INVOCATION_TRANSMISSION: - if element.transmission.initial_metadata: - initial_metadata = self._implementation.invocation_initial_metadata() - self._state.invocation_initial_metadata_in_fight = initial_metadata - else: - initial_metadata = None - if element.transmission.payload: - payload = _create_payload(self._randomness) - self._state.invocation_payloads_in_flight.append(payload) - self._state.invocation_side_invocation_allowance -= 1 - else: - payload = None - if element.transmission.complete: - completion = self._implementation.invocation_completion() - self._state.invocation_completion_in_flight = completion - else: - completion = None - if (not self._state.service_completion_received and - 0 <= self._state.invocation_side_service_allowance): - allowance = 1 - self._state.invocation_side_service_allowance += 1 - self._state.service_allowance_in_flight += 1 - else: - allowance = None - return OnAdvance( - OnAdvance.Kind.ADVANCE, initial_metadata, payload, completion, - allowance) - else: - raise ValueError('TODO!!!') - else: - return _IDLE_ON_ADVANCE - - def service_on_termination(self, outcome): - with self._condition: - self._state.service_side_outcome = outcome - if self._todo is not None or self._remaining_elements: - self._failed('Premature service-side outcome %s!' % (outcome,)) - elif outcome.kind is not self._sequence.outcome_kinds.service: - self._failed( - 'Incorrect service-side outcome kind: %s should have been %s' % ( - outcome.kind, self._sequence.outcome_kinds.service)) - elif self._state.invocation_side_outcome is not None: - self._passed(self._state.invocation_side_outcome.kind, outcome.kind) - - def invocation_on_termination(self, outcome): - with self._condition: - self._state.invocation_side_outcome = outcome - if self._todo is not None or self._remaining_elements: - self._failed('Premature invocation-side outcome %s!' % (outcome,)) - elif outcome.kind is not self._sequence.outcome_kinds.invocation: - self._failed( - 'Incorrect invocation-side outcome kind: %s should have been %s' % ( - outcome.kind, self._sequence.outcome_kinds.invocation)) - elif self._state.service_side_outcome is not None: - self._passed(outcome.kind, self._state.service_side_outcome.kind) - - -class _SequenceControllerCreator(ControllerCreator): - - def __init__(self, sequence): - self._sequence = sequence - - def name(self): - return self._sequence.name - - def controller(self, implementation, randomness): - return _SequenceController(self._sequence, implementation, randomness) - - -CONTROLLER_CREATORS = tuple( - _SequenceControllerCreator(sequence) for sequence in _sequence.SEQUENCES) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_sequence.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_sequence.py deleted file mode 100644 index 571d0e1e63..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_sequence.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Part of the tests of the base interface of RPC Framework.""" - -import collections -import enum - -from grpc.framework.interfaces.base import base -from tests.unit.framework.common import test_constants - - -class Invocation( - collections.namedtuple( - 'Invocation', ('timeout', 'initial_metadata', 'payload', 'complete',))): - """A recipe for operation invocation. - - Attributes: - timeout: A duration in seconds to pass to the system under test as the - operation's timeout value. - initial_metadata: A boolean indicating whether or not to pass initial - metadata when invoking the operation. - payload: A boolean indicating whether or not to pass a payload when - invoking the operation. - complete: A boolean indicating whether or not to indicate completion of - transmissions from the invoking side of the operation when invoking the - operation. - """ - - -class Transmission( - collections.namedtuple( - 'Transmission', ('initial_metadata', 'payload', 'complete',))): - """A recipe for a single transmission in an operation. - - Attributes: - initial_metadata: A boolean indicating whether or not to pass initial - metadata as part of the transmission. - payload: A boolean indicating whether or not to pass a payload as part of - the transmission. - complete: A boolean indicating whether or not to indicate completion of - transmission from the transmitting side of the operation as part of the - transmission. - """ - - -class Intertransmission( - collections.namedtuple('Intertransmission', ('invocation', 'service',))): - """A recipe for multiple transmissions in an operation. - - Attributes: - invocation: An integer describing the number of payloads to send from the - invocation side of the operation to the service side. - service: An integer describing the number of payloads to send from the - service side of the operation to the invocation side. - """ - - -class Element(collections.namedtuple('Element', ('kind', 'transmission',))): - """A sum type for steps to perform when testing an operation. - - Attributes: - kind: A Kind value describing the kind of step to perform in the test. - transmission: Only valid for kinds Kind.INVOCATION_TRANSMISSION and - Kind.SERVICE_TRANSMISSION, a Transmission value describing the details of - the transmission to be made. - """ - - @enum.unique - class Kind(enum.Enum): - INVOCATION_TRANSMISSION = 'invocation transmission' - SERVICE_TRANSMISSION = 'service transmission' - INTERTRANSMISSION = 'intertransmission' - INVOCATION_CANCEL = 'invocation cancel' - SERVICE_CANCEL = 'service cancel' - INVOCATION_FAILURE = 'invocation failure' - SERVICE_FAILURE = 'service failure' - - -class OutcomeKinds( - collections.namedtuple('Outcome', ('invocation', 'service',))): - """A description of the expected outcome of an operation test. - - Attributes: - invocation: The base.Outcome.Kind value expected on the invocation side of - the operation. - service: The base.Outcome.Kind value expected on the service side of the - operation. - """ - - -class Sequence( - collections.namedtuple( - 'Sequence', - ('name', 'maximum_duration', 'invocation', 'elements', - 'outcome_kinds',))): - """Describes at a high level steps to perform in a test. - - Attributes: - name: The string name of the sequence. - maximum_duration: A length of time in seconds to allow for the test before - declaring it to have failed. - invocation: An Invocation value describing how to invoke the operation - under test. - elements: A sequence of Element values describing at coarse granularity - actions to take during the operation under test. - outcome_kinds: An OutcomeKinds value describing the expected outcome kinds - of the test. - """ - -_EASY = Sequence( - 'Easy', - test_constants.TIME_ALLOWANCE, - Invocation(test_constants.LONG_TIMEOUT, True, True, True), - ( - Element( - Element.Kind.SERVICE_TRANSMISSION, Transmission(True, True, True)), - ), - OutcomeKinds(base.Outcome.Kind.COMPLETED, base.Outcome.Kind.COMPLETED)) - -_PEASY = Sequence( - 'Peasy', - test_constants.TIME_ALLOWANCE, - Invocation(test_constants.LONG_TIMEOUT, True, True, False), - ( - Element( - Element.Kind.SERVICE_TRANSMISSION, Transmission(True, True, False)), - Element( - Element.Kind.INVOCATION_TRANSMISSION, - Transmission(False, True, True)), - Element( - Element.Kind.SERVICE_TRANSMISSION, Transmission(False, True, True)), - ), - OutcomeKinds(base.Outcome.Kind.COMPLETED, base.Outcome.Kind.COMPLETED)) - - -# TODO(issue 2959): Finish this test suite. This tuple of sequences should -# contain at least the values in the Cartesian product of (half-duplex, -# full-duplex) * (zero payloads, one payload, test_constants.STREAM_LENGTH -# payloads) * (completion, cancellation, expiration, programming defect in -# servicer code). -SEQUENCES = ( - _EASY, - _PEASY, -) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_state.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_state.py deleted file mode 100644 index 21cf33aeb6..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/_state.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Part of the tests of the base interface of RPC Framework.""" - - -class OperationState(object): - - def __init__(self): - self.invocation_initial_metadata_in_flight = None - self.invocation_initial_metadata_received = False - self.invocation_payloads_in_flight = [] - self.invocation_payloads_received = 0 - self.invocation_completion_in_flight = None - self.invocation_completion_received = False - self.service_initial_metadata_in_flight = None - self.service_initial_metadata_received = False - self.service_payloads_in_flight = [] - self.service_payloads_received = 0 - self.service_completion_in_flight = None - self.service_completion_received = False - self.invocation_side_invocation_allowance = 1 - self.invocation_side_service_allowance = 1 - self.service_side_invocation_allowance = 1 - self.service_side_service_allowance = 1 - self.invocation_allowance_in_flight = 0 - self.service_allowance_in_flight = 0 - self.invocation_side_outcome = None - self.service_side_outcome = None diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/test_cases.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/base/test_cases.py deleted file mode 100644 index 5d16bf98be..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/test_cases.py +++ /dev/null @@ -1,279 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Tests of the base interface of RPC Framework.""" - -from __future__ import division - -import logging -import random -import threading -import time -import unittest - -from grpc.framework.foundation import logging_pool -from grpc.framework.interfaces.base import base -from grpc.framework.interfaces.base import utilities -from tests.unit.framework.common import test_constants -from tests.unit.framework.interfaces.base import _control -from tests.unit.framework.interfaces.base import test_interfaces - -_SYNCHRONICITY_VARIATION = (('Sync', False), ('Async', True)) - -_EMPTY_OUTCOME_KIND_DICT = { - outcome_kind: 0 for outcome_kind in base.Outcome.Kind} - - -class _Serialization(test_interfaces.Serialization): - - def serialize_request(self, request): - return request + request - - def deserialize_request(self, serialized_request): - return serialized_request[:len(serialized_request) // 2] - - def serialize_response(self, response): - return response * 3 - - def deserialize_response(self, serialized_response): - return serialized_response[2 * len(serialized_response) // 3:] - - -def _advance(quadruples, operator, controller): - try: - for quadruple in quadruples: - operator.advance( - initial_metadata=quadruple[0], payload=quadruple[1], - completion=quadruple[2], allowance=quadruple[3]) - except Exception as e: # pylint: disable=broad-except - controller.failed('Exception on advance: %e' % e) - - -class _Operator(base.Operator): - - def __init__(self, controller, on_advance, pool, operator_under_test): - self._condition = threading.Condition() - self._controller = controller - self._on_advance = on_advance - self._pool = pool - self._operator_under_test = operator_under_test - self._pending_advances = [] - - def set_operator_under_test(self, operator_under_test): - with self._condition: - self._operator_under_test = operator_under_test - pent_advances = self._pending_advances - self._pending_advances = [] - pool = self._pool - controller = self._controller - - if pool is None: - _advance(pent_advances, operator_under_test, controller) - else: - pool.submit(_advance, pent_advances, operator_under_test, controller) - - def advance( - self, initial_metadata=None, payload=None, completion=None, - allowance=None): - on_advance = self._on_advance( - initial_metadata, payload, completion, allowance) - if on_advance.kind is _control.OnAdvance.Kind.ADVANCE: - with self._condition: - pool = self._pool - operator_under_test = self._operator_under_test - controller = self._controller - - quadruple = ( - on_advance.initial_metadata, on_advance.payload, - on_advance.completion, on_advance.allowance) - if pool is None: - _advance((quadruple,), operator_under_test, controller) - else: - pool.submit(_advance, (quadruple,), operator_under_test, controller) - elif on_advance.kind is _control.OnAdvance.Kind.DEFECT: - raise ValueError( - 'Deliberately raised exception from Operator.advance (in a test)!') - - -class _ProtocolReceiver(base.ProtocolReceiver): - - def __init__(self): - self._condition = threading.Condition() - self._contexts = [] - - def context(self, protocol_context): - with self._condition: - self._contexts.append(protocol_context) - - -class _Servicer(base.Servicer): - """A base.Servicer with instrumented for testing.""" - - def __init__(self, group, method, controllers, pool): - self._condition = threading.Condition() - self._group = group - self._method = method - self._pool = pool - self._controllers = list(controllers) - - def service(self, group, method, context, output_operator): - with self._condition: - controller = self._controllers.pop(0) - if group != self._group or method != self._method: - controller.fail( - '%s != %s or %s != %s' % (group, self._group, method, self._method)) - raise base.NoSuchMethodError(None, None) - else: - operator = _Operator( - controller, controller.on_service_advance, self._pool, - output_operator) - outcome = context.add_termination_callback( - controller.service_on_termination) - if outcome is not None: - controller.service_on_termination(outcome) - return utilities.full_subscription(operator, _ProtocolReceiver()) - - -class _OperationTest(unittest.TestCase): - - def setUp(self): - if self._synchronicity_variation: - self._pool = logging_pool.pool(test_constants.POOL_SIZE) - else: - self._pool = None - self._controller = self._controller_creator.controller( - self._implementation, self._randomness) - - def tearDown(self): - if self._synchronicity_variation: - self._pool.shutdown(wait=True) - else: - self._pool = None - - def test_operation(self): - invocation = self._controller.invocation() - if invocation.subscription_kind is base.Subscription.Kind.FULL: - test_operator = _Operator( - self._controller, self._controller.on_invocation_advance, - self._pool, None) - subscription = utilities.full_subscription( - test_operator, _ProtocolReceiver()) - else: - # TODO(nathaniel): support and test other subscription kinds. - self.fail('Non-full subscriptions not yet supported!') - - servicer = _Servicer( - invocation.group, invocation.method, (self._controller,), self._pool) - - invocation_end, service_end, memo = self._implementation.instantiate( - {(invocation.group, invocation.method): _Serialization()}, servicer) - - try: - invocation_end.start() - service_end.start() - operation_context, operator_under_test = invocation_end.operate( - invocation.group, invocation.method, subscription, invocation.timeout, - initial_metadata=invocation.initial_metadata, payload=invocation.payload, - completion=invocation.completion) - test_operator.set_operator_under_test(operator_under_test) - outcome = operation_context.add_termination_callback( - self._controller.invocation_on_termination) - if outcome is not None: - self._controller.invocation_on_termination(outcome) - except Exception as e: # pylint: disable=broad-except - self._controller.failed('Exception on invocation: %s' % e) - self.fail(e) - - while True: - instruction = self._controller.poll() - if instruction.kind is _control.Instruction.Kind.ADVANCE: - try: - test_operator.advance( - *instruction.advance_args, **instruction.advance_kwargs) - except Exception as e: # pylint: disable=broad-except - self._controller.failed('Exception on instructed advance: %s' % e) - elif instruction.kind is _control.Instruction.Kind.CANCEL: - try: - operation_context.cancel() - except Exception as e: # pylint: disable=broad-except - self._controller.failed('Exception on cancel: %s' % e) - elif instruction.kind is _control.Instruction.Kind.CONCLUDE: - break - - invocation_stop_event = invocation_end.stop(0) - service_stop_event = service_end.stop(0) - invocation_stop_event.wait() - service_stop_event.wait() - invocation_stats = invocation_end.operation_stats() - service_stats = service_end.operation_stats() - - self._implementation.destantiate(memo) - - self.assertTrue( - instruction.conclude_success, msg=instruction.conclude_message) - - expected_invocation_stats = dict(_EMPTY_OUTCOME_KIND_DICT) - expected_invocation_stats[ - instruction.conclude_invocation_outcome_kind] += 1 - self.assertDictEqual(expected_invocation_stats, invocation_stats) - expected_service_stats = dict(_EMPTY_OUTCOME_KIND_DICT) - expected_service_stats[instruction.conclude_service_outcome_kind] += 1 - self.assertDictEqual(expected_service_stats, service_stats) - - -def test_cases(implementation): - """Creates unittest.TestCase classes for a given Base implementation. - - Args: - implementation: A test_interfaces.Implementation specifying creation and - destruction of the Base implementation under test. - - Returns: - A sequence of subclasses of unittest.TestCase defining tests of the - specified Base layer implementation. - """ - random_seed = hash(time.time()) - logging.warning('Random seed for this execution: %s', random_seed) - randomness = random.Random(x=random_seed) - - test_case_classes = [] - for synchronicity_variation in _SYNCHRONICITY_VARIATION: - for controller_creator in _control.CONTROLLER_CREATORS: - name = ''.join( - (synchronicity_variation[0], controller_creator.name(), 'Test',)) - test_case_classes.append( - type(name, (_OperationTest,), - {'_implementation': implementation, - '_randomness': randomness, - '_synchronicity_variation': synchronicity_variation[1], - '_controller_creator': controller_creator, - '__module__': implementation.__module__, - })) - - return test_case_classes diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/test_interfaces.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/base/test_interfaces.py deleted file mode 100644 index 5eba475ba8..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/base/test_interfaces.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Interfaces used in tests of implementations of the Base layer.""" - -import abc - -import six - -from grpc.framework.interfaces.base import base # pylint: disable=unused-import - - -class Serialization(six.with_metaclass(abc.ABCMeta)): - """Specifies serialization and deserialization of test payloads.""" - - def serialize_request(self, request): - """Serializes a request value used in a test. - - Args: - request: A request value created by a test. - - Returns: - A bytestring that is the serialization of the given request. - """ - raise NotImplementedError() - - def deserialize_request(self, serialized_request): - """Deserializes a request value used in a test. - - Args: - serialized_request: A bytestring that is the serialization of some request - used in a test. - - Returns: - The request value encoded by the given bytestring. - """ - raise NotImplementedError() - - def serialize_response(self, response): - """Serializes a response value used in a test. - - Args: - response: A response value created by a test. - - Returns: - A bytestring that is the serialization of the given response. - """ - raise NotImplementedError() - - def deserialize_response(self, serialized_response): - """Deserializes a response value used in a test. - - Args: - serialized_response: A bytestring that is the serialization of some - response used in a test. - - Returns: - The response value encoded by the given bytestring. - """ - raise NotImplementedError() - - -class Implementation(six.with_metaclass(abc.ABCMeta)): - """Specifies an implementation of the Base layer.""" - - @abc.abstractmethod - def instantiate(self, serializations, servicer): - """Instantiates the Base layer implementation to be used in a test. - - Args: - serializations: A dict from group-method pair to Serialization object - specifying how to serialize and deserialize payload values used in the - test. - servicer: A base.Servicer object to be called to service RPCs made during - the test. - - Returns: - A sequence of length three the first element of which is a - base.End to be used to invoke RPCs, the second element of which is a - base.End to be used to service invoked RPCs, and the third element of - which is an arbitrary memo object to be kept and passed to destantiate - at the conclusion of the test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def destantiate(self, memo): - """Destroys the Base layer implementation under test. - - Args: - memo: The object from the third position of the return value of a call to - instantiate. - """ - raise NotImplementedError() - - @abc.abstractmethod - def invocation_initial_metadata(self): - """Provides an operation's invocation-side initial metadata. - - Returns: - A value to use for an operation's invocation-side initial metadata, or - None. - """ - raise NotImplementedError() - - @abc.abstractmethod - def service_initial_metadata(self): - """Provides an operation's service-side initial metadata. - - Returns: - A value to use for an operation's service-side initial metadata, or - None. - """ - raise NotImplementedError() - - @abc.abstractmethod - def invocation_completion(self): - """Provides an operation's invocation-side completion. - - Returns: - A base.Completion to use for an operation's invocation-side completion. - """ - raise NotImplementedError() - - @abc.abstractmethod - def service_completion(self): - """Provides an operation's service-side completion. - - Returns: - A base.Completion to use for an operation's service-side completion. - """ - raise NotImplementedError() - - @abc.abstractmethod - def metadata_transmitted(self, original_metadata, transmitted_metadata): - """Identifies whether or not metadata was properly transmitted. - - Args: - original_metadata: A metadata value passed to the system under test. - transmitted_metadata: The same metadata value after having been - transmitted through the system under test. - - Returns: - Whether or not the metadata was properly transmitted. - """ - raise NotImplementedError() - - @abc.abstractmethod - def completion_transmitted(self, original_completion, transmitted_completion): - """Identifies whether or not a base.Completion was properly transmitted. - - Args: - original_completion: A base.Completion passed to the system under test. - transmitted_completion: The same completion value after having been - transmitted through the system under test. - - Returns: - Whether or not the completion was properly transmitted. - """ - raise NotImplementedError() diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py index 791620307b..df620b19ba 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py @@ -41,6 +41,7 @@ from concurrent import futures import six # test_interfaces is referenced from specification in this module. +from grpc.framework.foundation import future from grpc.framework.foundation import logging_pool from grpc.framework.interfaces.face import face from tests.unit.framework.common import test_constants @@ -159,6 +160,8 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. test_messages.verify(request, response, self) self.assertIs(callback.future(), response_future) + self.assertIsNone(response_future.exception()) + self.assertIsNone(response_future.traceback()) def testSuccessfulUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -191,6 +194,8 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. test_messages.verify(requests, response, self) self.assertIs(future_passed_to_callback, response_future) + self.assertIsNone(response_future.exception()) + self.assertIsNone(response_future.traceback()) def testSuccessfulStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -301,6 +306,12 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. self.assertIs(callback.future(), response_future) self.assertFalse(cancel_method_return_value) self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() + with self.assertRaises(future.CancelledError): + response_future.exception() + with self.assertRaises(future.CancelledError): + response_future.traceback() def testCancelledUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -332,6 +343,12 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. self.assertIs(callback.future(), response_future) self.assertFalse(cancel_method_return_value) self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() + with self.assertRaises(future.CancelledError): + response_future.exception() + with self.assertRaises(future.CancelledError): + response_future.traceback() def testCancelledStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -363,6 +380,9 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() + self.assertIsInstance( + response_future.exception(), face.AbortionError) + self.assertIsNotNone(response_future.traceback()) def testExpiredUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -392,6 +412,9 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() + self.assertIsInstance( + response_future.exception(), face.AbortionError) + self.assertIsNotNone(response_future.traceback()) def testExpiredStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -411,11 +434,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. for test_messages in test_messages_sequence: request = test_messages.request() callback = _Callback() + abortion_callback = _Callback() with self._control.fail(): response_future = self._invoker.future(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) + response_future.add_abortion_callback(abortion_callback) self.assertIs(callback.future(), response_future) # Because the servicer fails outside of the thread from which the @@ -426,6 +451,8 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() + self.assertIsNotNone(response_future.traceback()) + self.assertIsNotNone(abortion_callback.future()) def testFailedUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -448,11 +475,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. for test_messages in test_messages_sequence: requests = test_messages.requests() callback = _Callback() + abortion_callback = _Callback() with self._control.fail(): response_future = self._invoker.future(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) + response_future.add_abortion_callback(abortion_callback) self.assertIs(callback.future(), response_future) # Because the servicer fails outside of the thread from which the @@ -463,6 +492,8 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() + self.assertIsNotNone(response_future.traceback()) + self.assertIsNotNone(abortion_callback.future()) def testFailedStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_receiver.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_receiver.py deleted file mode 100644 index 48f31fc677..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_receiver.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""A utility useful in tests of asynchronous, event-driven interfaces.""" - -import threading - -from grpc.framework.interfaces.face import face - - -class Receiver(face.ResponseReceiver): - """A utility object useful in tests of asynchronous code.""" - - def __init__(self): - self._condition = threading.Condition() - self._initial_metadata = None - self._responses = [] - self._terminal_metadata = None - self._code = None - self._details = None - self._completed = False - self._abortion = None - - def abort(self, abortion): - with self._condition: - self._abortion = abortion - self._condition.notify_all() - - def initial_metadata(self, initial_metadata): - with self._condition: - self._initial_metadata = initial_metadata - - def response(self, response): - with self._condition: - self._responses.append(response) - - def complete(self, terminal_metadata, code, details): - with self._condition: - self._terminal_metadata = terminal_metadata - self._code = code - self._details = details - self._completed = True - self._condition.notify_all() - - def block_until_terminated(self): - with self._condition: - while self._abortion is None and not self._completed: - self._condition.wait() - - def unary_response(self): - with self._condition: - if self._abortion is not None: - raise AssertionError('Aborted: "{}"!'.format(self._abortion)) - elif len(self._responses) != 1: - raise AssertionError( - '%d responses received, not exactly one!', len(self._responses)) - else: - return self._responses[0] - - def stream_responses(self): - with self._condition: - if self._abortion is None: - return list(self._responses) - else: - raise AssertionError('Aborted: "{}"!'.format(self._abortion)) - - def abortion(self): - with self._condition: - return self._abortion diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/__init__.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/links/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_cases.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_cases.py deleted file mode 100644 index 608e64119e..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_cases.py +++ /dev/null @@ -1,327 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Tests of the links interface of RPC Framework.""" - -# unittest is referenced from specification in this module. -import abc -import unittest # pylint: disable=unused-import - -import six - -from grpc.framework.interfaces.links import links -from tests.unit.framework.common import test_constants -from tests.unit.framework.interfaces.links import test_utilities - - -def at_least_n_payloads_received_predicate(n): - def predicate(ticket_sequence): - payload_count = 0 - for ticket in ticket_sequence: - if ticket.payload is not None: - payload_count += 1 - if n <= payload_count: - return True - else: - return False - return predicate - - -def terminated(ticket_sequence): - return ticket_sequence and ticket_sequence[-1].termination is not None - -_TRANSMISSION_GROUP = 'test.Group' -_TRANSMISSION_METHOD = 'TestMethod' - - -class TransmissionTest(six.with_metaclass(abc.ABCMeta)): - """Tests ticket transmission between two connected links. - - This class must be mixed into a unittest.TestCase that implements the abstract - methods it provides. - """ - - # This is a unittest.TestCase mix-in. - # pylint: disable=invalid-name - - @abc.abstractmethod - def create_transmitting_links(self): - """Creates two connected links for use in this test. - - Returns: - Two links.Links, the first of which will be used on the invocation side - of RPCs and the second of which will be used on the service side of - RPCs. - """ - raise NotImplementedError() - - @abc.abstractmethod - def destroy_transmitting_links(self, invocation_side_link, service_side_link): - """Destroys the two connected links created for this test. - - - Args: - invocation_side_link: The link used on the invocation side of RPCs in - this test. - service_side_link: The link used on the service side of RPCs in this - test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_invocation_initial_metadata(self): - """Creates a value for use as invocation-side initial metadata. - - Returns: - A metadata value appropriate for use as invocation-side initial metadata - or None if invocation-side initial metadata transmission is not - supported by the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_invocation_terminal_metadata(self): - """Creates a value for use as invocation-side terminal metadata. - - Returns: - A metadata value appropriate for use as invocation-side terminal - metadata or None if invocation-side terminal metadata transmission is - not supported by the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_service_initial_metadata(self): - """Creates a value for use as service-side initial metadata. - - Returns: - A metadata value appropriate for use as service-side initial metadata or - None if service-side initial metadata transmission is not supported by - the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_service_terminal_metadata(self): - """Creates a value for use as service-side terminal metadata. - - Returns: - A metadata value appropriate for use as service-side terminal metadata or - None if service-side terminal metadata transmission is not supported by - the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_invocation_completion(self): - """Creates values for use as invocation-side code and message. - - Returns: - An invocation-side code value and an invocation-side message value. - Either or both may be None if invocation-side code and/or - invocation-side message transmission is not supported by the links - under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def create_service_completion(self): - """Creates values for use as service-side code and message. - - Returns: - A service-side code value and a service-side message value. Either or - both may be None if service-side code and/or service-side message - transmission is not supported by the links under test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def assertMetadataTransmitted(self, original_metadata, transmitted_metadata): - """Asserts that transmitted_metadata contains original_metadata. - - Args: - original_metadata: A metadata object used in this test. - transmitted_metadata: A metadata object obtained after transmission - through the system under test. - - Raises: - AssertionError: if the transmitted_metadata object does not contain - original_metadata. - """ - raise NotImplementedError() - - def group_and_method(self): - """Returns the group and method used in this test case. - - Returns: - A pair of the group and method used in this test case. - """ - return _TRANSMISSION_GROUP, _TRANSMISSION_METHOD - - def serialize_request(self, request): - """Serializes a request value used in this test case. - - Args: - request: A request value created by this test case. - - Returns: - A bytestring that is the serialization of the given request. - """ - return request - - def deserialize_request(self, serialized_request): - """Deserializes a request value used in this test case. - - Args: - serialized_request: A bytestring that is the serialization of some request - used in this test case. - - Returns: - The request value encoded by the given bytestring. - """ - return serialized_request - - def serialize_response(self, response): - """Serializes a response value used in this test case. - - Args: - response: A response value created by this test case. - - Returns: - A bytestring that is the serialization of the given response. - """ - return response - - def deserialize_response(self, serialized_response): - """Deserializes a response value used in this test case. - - Args: - serialized_response: A bytestring that is the serialization of some - response used in this test case. - - Returns: - The response value encoded by the given bytestring. - """ - return serialized_response - - def _assert_is_valid_metadata_payload_sequence( - self, ticket_sequence, payloads, initial_metadata, terminal_metadata): - initial_metadata_seen = False - seen_payloads = [] - terminal_metadata_seen = False - - for ticket in ticket_sequence: - if ticket.initial_metadata is not None: - self.assertFalse(initial_metadata_seen) - self.assertFalse(seen_payloads) - self.assertFalse(terminal_metadata_seen) - self.assertMetadataTransmitted(initial_metadata, ticket.initial_metadata) - initial_metadata_seen = True - - if ticket.payload is not None: - self.assertFalse(terminal_metadata_seen) - seen_payloads.append(ticket.payload) - - if ticket.terminal_metadata is not None: - self.assertFalse(terminal_metadata_seen) - self.assertMetadataTransmitted(terminal_metadata, ticket.terminal_metadata) - terminal_metadata_seen = True - self.assertSequenceEqual(payloads, seen_payloads) - - def _assert_is_valid_invocation_sequence( - self, ticket_sequence, group, method, payloads, initial_metadata, - terminal_metadata, termination): - self.assertLess(0, len(ticket_sequence)) - self.assertEqual(group, ticket_sequence[0].group) - self.assertEqual(method, ticket_sequence[0].method) - self._assert_is_valid_metadata_payload_sequence( - ticket_sequence, payloads, initial_metadata, terminal_metadata) - self.assertIs(termination, ticket_sequence[-1].termination) - - def _assert_is_valid_service_sequence( - self, ticket_sequence, payloads, initial_metadata, terminal_metadata, - code, message, termination): - self.assertLess(0, len(ticket_sequence)) - self._assert_is_valid_metadata_payload_sequence( - ticket_sequence, payloads, initial_metadata, terminal_metadata) - self.assertEqual(code, ticket_sequence[-1].code) - self.assertEqual(message, ticket_sequence[-1].message) - self.assertIs(termination, ticket_sequence[-1].termination) - - def setUp(self): - self._invocation_link, self._service_link = self.create_transmitting_links() - self._invocation_mate = test_utilities.RecordingLink() - self._service_mate = test_utilities.RecordingLink() - self._invocation_link.join_link(self._invocation_mate) - self._service_link.join_link(self._service_mate) - - def tearDown(self): - self.destroy_transmitting_links(self._invocation_link, self._service_link) - - def testSimplestRoundTrip(self): - """Tests transmission of one ticket in each direction.""" - invocation_operation_id = object() - invocation_payload = b'\x07' * 1023 - timeout = test_constants.LONG_TIMEOUT - invocation_initial_metadata = self.create_invocation_initial_metadata() - invocation_terminal_metadata = self.create_invocation_terminal_metadata() - invocation_code, invocation_message = self.create_invocation_completion() - service_payload = b'\x08' * 1025 - service_initial_metadata = self.create_service_initial_metadata() - service_terminal_metadata = self.create_service_terminal_metadata() - service_code, service_message = self.create_service_completion() - - original_invocation_ticket = links.Ticket( - invocation_operation_id, 0, _TRANSMISSION_GROUP, _TRANSMISSION_METHOD, - links.Ticket.Subscription.FULL, timeout, 0, invocation_initial_metadata, - invocation_payload, invocation_terminal_metadata, invocation_code, - invocation_message, links.Ticket.Termination.COMPLETION, None) - self._invocation_link.accept_ticket(original_invocation_ticket) - - self._service_mate.block_until_tickets_satisfy( - at_least_n_payloads_received_predicate(1)) - service_operation_id = self._service_mate.tickets()[0].operation_id - - self._service_mate.block_until_tickets_satisfy(terminated) - self._assert_is_valid_invocation_sequence( - self._service_mate.tickets(), _TRANSMISSION_GROUP, _TRANSMISSION_METHOD, - (invocation_payload,), invocation_initial_metadata, - invocation_terminal_metadata, links.Ticket.Termination.COMPLETION) - - original_service_ticket = links.Ticket( - service_operation_id, 0, None, None, links.Ticket.Subscription.FULL, - timeout, 0, service_initial_metadata, service_payload, - service_terminal_metadata, service_code, service_message, - links.Ticket.Termination.COMPLETION, None) - self._service_link.accept_ticket(original_service_ticket) - self._invocation_mate.block_until_tickets_satisfy(terminated) - self._assert_is_valid_service_sequence( - self._invocation_mate.tickets(), (service_payload,), - service_initial_metadata, service_terminal_metadata, service_code, - service_message, links.Ticket.Termination.COMPLETION) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_utilities.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_utilities.py deleted file mode 100644 index 39c7f2fc63..0000000000 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/links/test_utilities.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""State and behavior appropriate for use in tests.""" - -import logging -import threading -import time - -from grpc.framework.interfaces.links import links -from grpc.framework.interfaces.links import utilities - -# A more-or-less arbitrary limit on the length of raw data values to be logged. -_UNCOMFORTABLY_LONG = 48 - - -def _safe_for_log_ticket(ticket): - """Creates a safe-for-printing-to-the-log ticket for a given ticket. - - Args: - ticket: Any links.Ticket. - - Returns: - A links.Ticket that is as much as can be equal to the given ticket but - possibly features values like the string "<payload of length 972321>" in - place of the actual values of the given ticket. - """ - if isinstance(ticket.payload, (basestring,)): - payload_length = len(ticket.payload) - else: - payload_length = -1 - if payload_length < _UNCOMFORTABLY_LONG: - return ticket - else: - return links.Ticket( - ticket.operation_id, ticket.sequence_number, - ticket.group, ticket.method, ticket.subscription, ticket.timeout, - ticket.allowance, ticket.initial_metadata, - '<payload of length {}>'.format(payload_length), - ticket.terminal_metadata, ticket.code, ticket.message, - ticket.termination, None) - - -class RecordingLink(links.Link): - """A Link that records every ticket passed to it.""" - - def __init__(self): - self._condition = threading.Condition() - self._tickets = [] - - def accept_ticket(self, ticket): - with self._condition: - self._tickets.append(ticket) - self._condition.notify_all() - - def join_link(self, link): - pass - - def block_until_tickets_satisfy(self, predicate): - """Blocks until the received tickets satisfy the given predicate. - - Args: - predicate: A callable that takes a sequence of tickets and returns a - boolean value. - """ - with self._condition: - while not predicate(self._tickets): - self._condition.wait() - - def tickets(self): - """Returns a copy of the list of all tickets received by this Link.""" - with self._condition: - return tuple(self._tickets) - - -class _Pipe(object): - """A conduit that logs all tickets passed through it.""" - - def __init__(self, name): - self._lock = threading.Lock() - self._name = name - self._left_mate = utilities.NULL_LINK - self._right_mate = utilities.NULL_LINK - - def accept_left_to_right_ticket(self, ticket): - with self._lock: - logging.warning( - '%s: moving left to right through %s: %s', time.time(), self._name, - _safe_for_log_ticket(ticket)) - try: - self._right_mate.accept_ticket(ticket) - except Exception as e: # pylint: disable=broad-except - logging.exception(e) - - def accept_right_to_left_ticket(self, ticket): - with self._lock: - logging.warning( - '%s: moving right to left through %s: %s', time.time(), self._name, - _safe_for_log_ticket(ticket)) - try: - self._left_mate.accept_ticket(ticket) - except Exception as e: # pylint: disable=broad-except - logging.exception(e) - - def join_left_mate(self, left_mate): - with self._lock: - self._left_mate = utilities.NULL_LINK if left_mate is None else left_mate - - def join_right_mate(self, right_mate): - with self._lock: - self._right_mate = ( - utilities.NULL_LINK if right_mate is None else right_mate) - - -class _Facade(links.Link): - - def __init__(self, accept, join): - self._accept = accept - self._join = join - - def accept_ticket(self, ticket): - self._accept(ticket) - - def join_link(self, link): - self._join(link) - - -def logging_links(name): - """Creates a conduit that logs all tickets passed through it. - - Args: - name: A name to use for the conduit to identify itself in logging output. - - Returns: - Two links.Links, the first of which is the "left" side of the conduit - and the second of which is the "right" side of the conduit. - """ - pipe = _Pipe(name) - left_facade = _Facade(pipe.accept_left_to_right_ticket, pipe.join_left_mate) - right_facade = _Facade(pipe.accept_right_to_left_ticket, pipe.join_right_mate) - return left_facade, right_facade diff --git a/src/python/grpcio_tests/tests/unit/test_common.py b/src/python/grpcio_tests/tests/unit/test_common.py index c8886bf4ca..cd71bd80d7 100644 --- a/src/python/grpcio_tests/tests/unit/test_common.py +++ b/src/python/grpcio_tests/tests/unit/test_common.py @@ -31,6 +31,7 @@ import collections +import grpc import six INVOCATION_INITIAL_METADATA = (('0', 'abc'), ('1', 'def'), ('2', 'ghi'),) @@ -78,3 +79,24 @@ def metadata_transmitted(original_metadata, transmitted_metadata): return False else: return True + + +def test_secure_channel( + target, channel_credentials, server_host_override): + """Creates an insecure Channel to a remote host. + + Args: + host: The name of the remote host to which to connect. + port: The port of the remote host to which to connect. + channel_credentials: The implementations.ChannelCredentials with which to + connect. + server_host_override: The target name used for SSL host name checking. + + Returns: + An implementations.Channel to the remote host through which RPCs may be + conducted. + """ + channel = grpc.secure_channel( + target, channel_credentials, + (('grpc.ssl_target_name_override', server_host_override,),)) + return channel diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index f62397e79f..2126124443 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -71,6 +71,10 @@ static ID id_credentials; * received by the call and subsequently saved on it. */ static ID id_metadata; +/* id_trailing_metadata is the name of the attribute used to access the trailing + * metadata hash received by the call and subsequently saved on it. */ +static ID id_trailing_metadata; + /* id_status is name of the attribute used to access the status object * received by the call and subsequently saved on it. */ static ID id_status; @@ -298,6 +302,30 @@ static VALUE grpc_rb_call_set_metadata(VALUE self, VALUE metadata) { /* call-seq: + trailing_metadata = call.trailing_metadata + + Gets the trailing metadata object saved on the call */ +static VALUE grpc_rb_call_get_trailing_metadata(VALUE self) { + return rb_ivar_get(self, id_trailing_metadata); +} + +/* + call-seq: + call.trailing_metadata = trailing_metadata + + Saves the trailing metadata hash on the call. */ +static VALUE grpc_rb_call_set_trailing_metadata(VALUE self, VALUE metadata) { + if (!NIL_P(metadata) && TYPE(metadata) != T_HASH) { + rb_raise(rb_eTypeError, "bad metadata: got:<%s> want: <Hash>", + rb_obj_classname(metadata)); + return Qnil; + } + + return rb_ivar_set(self, id_trailing_metadata, metadata); +} + +/* + call-seq: write_flag = call.write_flag Gets the write_flag value saved the call. */ @@ -908,6 +936,10 @@ void Init_grpc_call() { rb_define_method(grpc_rb_cCall, "status=", grpc_rb_call_set_status, 1); rb_define_method(grpc_rb_cCall, "metadata", grpc_rb_call_get_metadata, 0); rb_define_method(grpc_rb_cCall, "metadata=", grpc_rb_call_set_metadata, 1); + rb_define_method(grpc_rb_cCall, "trailing_metadata", + grpc_rb_call_get_trailing_metadata, 0); + rb_define_method(grpc_rb_cCall, "trailing_metadata=", + grpc_rb_call_set_trailing_metadata, 1); rb_define_method(grpc_rb_cCall, "write_flag", grpc_rb_call_get_write_flag, 0); rb_define_method(grpc_rb_cCall, "write_flag=", grpc_rb_call_set_write_flag, 1); @@ -916,6 +948,7 @@ void Init_grpc_call() { /* Ids used to support call attributes */ id_metadata = rb_intern("metadata"); + id_trailing_metadata = rb_intern("trailing_metadata"); id_status = rb_intern("status"); id_write_flag = rb_intern("write_flag"); diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 18a15d0125..e6d30a174b 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -40,6 +40,7 @@ #include <grpc/grpc_security.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/time.h> #include "rb_grpc.h" #include "rb_call.h" #include "rb_channel_args.h" @@ -71,6 +72,7 @@ typedef struct grpc_rb_channel { /* The actual channel */ grpc_channel *wrapped; + grpc_completion_queue *queue; } grpc_rb_channel; /* Destroys Channel instances. */ @@ -83,6 +85,7 @@ static void grpc_rb_channel_free(void *p) { if (ch->wrapped != NULL) { grpc_channel_destroy(ch->wrapped); + grpc_rb_completion_queue_destroy(ch->queue); } xfree(p); @@ -165,6 +168,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { } rb_ivar_set(self, id_target, target); wrapper->wrapped = ch; + wrapper->queue = grpc_completion_queue_create(NULL); return self; } @@ -203,16 +207,18 @@ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, the completion queue with success=0 */ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, - VALUE cqueue, - VALUE deadline, - VALUE tag) { + VALUE deadline) { grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; grpc_completion_queue *cq = NULL; - cq = grpc_rb_get_wrapped_completion_queue(cqueue); + void *tag = wrapper; + + grpc_event event; + TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); ch = wrapper->wrapped; + cq = wrapper->queue; if (ch == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; @@ -222,9 +228,16 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, (grpc_connectivity_state)NUM2LONG(last_state), grpc_rb_time_timeval(deadline, /* absolute time */ 0), cq, - ROBJECT(tag)); + tag); - return Qnil; + event = rb_completion_queue_pluck(cq, tag, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + if (event.success) { + return Qtrue; + } else { + return Qfalse; + } } /* Create a call given a grpc_channel, in order to call method. The request diff --git a/src/ruby/ext/grpc/rb_completion_queue.h b/src/ruby/ext/grpc/rb_completion_queue.h index 9f8f6aa5ff..aa9dc6416a 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.h +++ b/src/ruby/ext/grpc/rb_completion_queue.h @@ -38,9 +38,6 @@ #include <grpc/grpc.h> -/* Gets the wrapped completion queue from the ruby wrapper */ -grpc_completion_queue *grpc_rb_get_wrapped_completion_queue(VALUE v); - void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq); /** diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index a3ac0d48a3..4260d85437 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -43,8 +43,7 @@ class Struct GRPC.logger.debug("Failing with status #{status}") # raise BadStatus, propagating the metadata if present. md = status.metadata - with_sym_keys = Hash[md.each_pair.collect { |x, y| [x.to_sym, y] }] - fail GRPC::BadStatus.new(status.code, status.details, with_sym_keys) + fail GRPC::BadStatus.new(status.code, status.details, md) end status end @@ -61,7 +60,7 @@ module GRPC extend Forwardable attr_reader(:deadline) def_delegators :@call, :cancel, :metadata, :write_flag, :write_flag=, - :peer, :peer_cert + :peer, :peer_cert, :trailing_metadata # client_invoke begins a client invocation. # @@ -120,7 +119,7 @@ module GRPC end # cancelled indicates if the call was cancelled - def cancelled + def cancelled? !@call.status.nil? && @call.status.code == Core::StatusCodes::CANCELLED end @@ -158,6 +157,9 @@ module GRPC ops[RECV_STATUS_ON_CLIENT] = nil if assert_finished batch_result = @call.run_batch(ops) return unless assert_finished + unless batch_result.status.nil? + @call.trailing_metadata = batch_result.status.metadata + end @call.status = batch_result.status op_is_done batch_result.check_status @@ -169,11 +171,7 @@ module GRPC def finished batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil) unless batch_result.status.nil? - if @call.metadata.nil? - @call.metadata = batch_result.status.metadata - else - @call.metadata.merge!(batch_result.status.metadata) - end + @call.trailing_metadata = batch_result.status.metadata end @call.status = batch_result.status op_is_done @@ -455,18 +453,18 @@ module GRPC # SingleReqView limits access to an ActiveCall's methods for use in server # handlers that receive just one request. - SingleReqView = view_class(:cancelled, :deadline, :metadata, + SingleReqView = view_class(:cancelled?, :deadline, :metadata, :output_metadata, :peer, :peer_cert) # MultiReqView limits access to an ActiveCall's methods for use in # server client_streamer handlers. - MultiReqView = view_class(:cancelled, :deadline, :each_queued_msg, + MultiReqView = view_class(:cancelled?, :deadline, :each_queued_msg, :each_remote_read, :metadata, :output_metadata) # Operation limits access to an ActiveCall's methods for use as # a Operation on the client. - Operation = view_class(:cancel, :cancelled, :deadline, :execute, + Operation = view_class(:cancel, :cancelled?, :deadline, :execute, :metadata, :status, :start_call, :wait, :write_flag, - :write_flag=) + :write_flag=, :trailing_metadata) end end diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb index 425dc3e519..c2ac3c4daf 100644 --- a/src/ruby/lib/grpc/generic/bidi_call.rb +++ b/src/ruby/lib/grpc/generic/bidi_call.rb @@ -76,7 +76,7 @@ module GRPC # block that can be invoked with each response. # # @param requests the Enumerable of requests to send - # @op_notifier a Notifier used to signal completion + # @param op_notifier a Notifier used to signal completion # @return an Enumerator of requests to yield def run_on_client(requests, op_notifier, &blk) @op_notifier = op_notifier diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb index 9d6bd3bf59..0d7c1f7805 100644 --- a/src/ruby/lib/grpc/generic/client_stub.rb +++ b/src/ruby/lib/grpc/generic/client_stub.rb @@ -34,7 +34,8 @@ require_relative '../version' module GRPC # rubocop:disable Metrics/ParameterLists - # ClientStub represents an endpoint used to send requests to GRPC servers. + # ClientStub represents a client connection to a gRPC server, and can be used + # to send requests. class ClientStub include Core::StatusCodes include Core::TimeConsts @@ -75,8 +76,9 @@ module GRPC # my_stub = ClientStub.new(example.host.com:50505, # :this_channel_is_insecure) # - # Any arbitrary keyword arguments are treated as channel arguments used to - # configure the RPC connection to the host. + # If a channel_override argument is passed, it will be used as the + # underlying channel. Otherwise, the channel_args argument will be used + # to construct a new underlying channel. # # There are some specific keyword args that are not used to configure the # channel: @@ -91,10 +93,17 @@ module GRPC # # @param host [String] the host the stub connects to # @param creds [Core::ChannelCredentials|Symbol] the channel credentials, or - # :this_channel_is_insecure + # :this_channel_is_insecure, which explicitly indicates that the client + # should be created with an insecure connection. Note: this argument is + # ignored if the channel_override argument is provided. # @param channel_override [Core::Channel] a pre-created channel # @param timeout [Number] the default timeout to use in requests - # @param channel_args [Hash] the channel arguments + # @param propagate_mask [Number] A bitwise combination of flags in + # GRPC::Core::PropagateMasks. Indicates how data should be propagated + # from parent server calls to child client calls if this client is being + # used within a gRPC server. + # @param channel_args [Hash] the channel arguments. Note: this argument is + # ignored if the channel_override argument is provided. def initialize(host, creds, channel_override: nil, timeout: nil, @@ -389,11 +398,11 @@ module GRPC # @param marshal [Function] f(obj)->string that marshals requests # @param unmarshal [Function] f(string)->obj that unmarshals responses # @param deadline [Time] (optional) the time the request should complete + # @param return_op [true|false] return an Operation if true # @param parent [Core::Call] a prior call whose reserved metadata # will be propagated by this one. # @param credentials [Core::CallCredentials] credentials to use when making # the call - # @param return_op [true|false] return an Operation if true # @param metadata [Hash] metadata to be sent to the server # @param blk [Block] when provided, is executed for each response # @return [Enumerator|nil|Operation] as discussed above @@ -430,7 +439,8 @@ module GRPC # @param unmarshal [Function] f(string)->obj that unmarshals responses # @param parent [Grpc::Call] a parent call, available when calls are # made from server - # @param timeout [TimeConst] + # @param credentials [Core::CallCredentials] credentials to use when making + # the call def new_active_call(method, marshal, unmarshal, deadline: nil, parent: nil, diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index c92a532a50..7ea2371365 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -172,22 +172,18 @@ module GRPC # The RPC server is configured using keyword arguments. # # There are some specific keyword args used to configure the RpcServer - # instance, however other arbitrary are allowed and when present are used - # to configure the listeninng connection set up by the RpcServer. - # - # * poll_period: when present, the server polls for new events with this - # period + # instance. # # * pool_size: the size of the thread pool the server uses to run its # threads # - # * creds: [GRPC::Core::ServerCredentials] - # the credentials used to secure the server - # # * max_waiting_requests: the maximum number of requests that are not # being handled to allow. When this limit is exceeded, the server responds # with not available to new requests # + # * poll_period: when present, the server polls for new events with this + # period + # # * connect_md_proc: # when non-nil is a proc for determining metadata to to send back the client # on receiving an invocation req. The proc signature is: diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 5e6aaef2eb..e57fb3c14f 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '0.16.0.dev' + VERSION = '1.0.0.pre1' end diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb index 146623e0ab..066a7bb90f 100755 --- a/src/ruby/pb/test/client.rb +++ b/src/ruby/pb/test/client.rb @@ -369,7 +369,7 @@ class NamedTests op.execute fail 'Should have raised GRPC:Cancelled' rescue GRPC::Cancelled - assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled } + assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled? } end def cancel_after_first_response @@ -380,7 +380,7 @@ class NamedTests op.execute.each { |r| ppp.queue.push(r) } fail 'Should have raised GRPC:Cancelled' rescue GRPC::Cancelled - assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled } + assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled? } op.wait end diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb index b4e6f9ee02..018580e0df 100644 --- a/src/ruby/spec/generic/active_call_spec.rb +++ b/src/ruby/spec/generic/active_call_spec.rb @@ -61,7 +61,7 @@ describe GRPC::ActiveCall do describe '#multi_req_view' do it 'exposes a fixed subset of the ActiveCall methods' do - want = %w(cancelled, deadline, each_remote_read, metadata, shutdown) + want = %w(cancelled?, deadline, each_remote_read, metadata, shutdown) v = @client_call.multi_req_view want.each do |w| expect(v.methods.include?(w)) @@ -71,7 +71,7 @@ describe GRPC::ActiveCall do describe '#single_req_view' do it 'exposes a fixed subset of the ActiveCall methods' do - want = %w(cancelled, deadline, metadata, shutdown) + want = %w(cancelled?, deadline, metadata, shutdown) v = @client_call.single_req_view want.each do |w| expect(v.methods.include?(w)) diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb index 901c84fc78..31157cf161 100644 --- a/src/ruby/spec/generic/rpc_server_spec.rb +++ b/src/ruby/spec/generic/rpc_server_spec.rb @@ -95,7 +95,7 @@ class FailingService def initialize(_default_var = 'ignored') @details = 'app error' @code = 101 - @md = { failed_method: 'an_rpc' } + @md = { 'failed_method' => 'an_rpc' } end def an_rpc(_req, _call) @@ -515,7 +515,7 @@ describe GRPC::RpcServer do op = stub.an_rpc(req, return_op: true, metadata: { k1: 'v1', k2: 'v2' }) expect(op.metadata).to be nil expect(op.execute).to be_a(EchoMsg) - expect(op.metadata).to eq(wanted_trailers) + expect(op.trailing_metadata).to eq(wanted_trailers) @srv.stop t.join end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 68c1bf369d..2e318b82ad 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '0.16.0.dev' + VERSION = '1.0.0.pre1' end end |