diff options
Diffstat (limited to 'src')
162 files changed, 7942 insertions, 1137 deletions
diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 4841da8da8..242ce06a16 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -101,18 +101,20 @@ class IndentScope { // TODO(https://github.com/google/protobuf/issues/888): // Export `ModuleName` from protobuf's // `src/google/protobuf/compiler/python/python_generator.cc` file. -grpc::string ModuleName(const grpc::string& filename) { +grpc::string ModuleName(const grpc::string& filename, + const grpc::string& import_prefix) { grpc::string basename = StripProto(filename); basename = StringReplace(basename, "-", "_"); basename = StringReplace(basename, "/", "."); - return basename + "_pb2"; + return import_prefix + basename + "_pb2"; } // TODO(https://github.com/google/protobuf/issues/888): // Export `ModuleAlias` from protobuf's // `src/google/protobuf/compiler/python/python_generator.cc` file. -grpc::string ModuleAlias(const grpc::string& filename) { - grpc::string module_name = ModuleName(filename); +grpc::string ModuleAlias(const grpc::string& filename, + const grpc::string& import_prefix) { + grpc::string module_name = ModuleName(filename, import_prefix); // We can't have dots in the module name, so we replace each with _dot_. // But that could lead to a collision between a.b and a_dot_b, so we also // duplicate each underscore. @@ -189,7 +191,7 @@ bool PrivateGenerator::GetModuleAndMessagePath(const Descriptor* type, grpc::string generator_file_name = file->name(); grpc::string module; if (generator_file_name != file_name || generate_in_pb2_grpc) { - module = ModuleAlias(file_name) + "."; + module = ModuleAlias(file_name, config.import_prefix) + "."; } else { module = ""; } @@ -666,8 +668,10 @@ bool PrivateGenerator::PrintPreamble() { for (int k = 0; k < 2; ++k) { const Descriptor* type = types[k]; grpc::string type_file_name = type->file()->name(); - grpc::string module_name = ModuleName(type_file_name); - grpc::string module_alias = ModuleAlias(type_file_name); + grpc::string module_name = + ModuleName(type_file_name, config.import_prefix); + grpc::string module_alias = + ModuleAlias(type_file_name, config.import_prefix); imports_set.insert(std::make_tuple(module_name, module_alias)); } } @@ -766,7 +770,9 @@ pair<bool, grpc::string> PrivateGenerator::GetGrpcServices() { } // namespace GeneratorConfiguration::GeneratorConfiguration() - : grpc_package_root("grpc"), beta_package_root("grpc.beta") {} + : grpc_package_root("grpc"), + beta_package_root("grpc.beta"), + import_prefix("") {} PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config) : config_(config) {} diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h index 6a95255d40..b91059fad7 100644 --- a/src/compiler/python_generator.h +++ b/src/compiler/python_generator.h @@ -45,7 +45,10 @@ namespace grpc_python_generator { struct GeneratorConfiguration { GeneratorConfiguration(); grpc::string grpc_package_root; + // TODO(https://github.com/grpc/grpc/issues/8622): Drop this. grpc::string beta_package_root; + // TODO(https://github.com/google/protobuf/issues/888): Drop this. + grpc::string import_prefix; }; class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c index b80d831557..fc29dbd454 100644 --- a/src/core/ext/census/grpc_filter.c +++ b/src/core/ext/census/grpc_filter.c @@ -138,7 +138,7 @@ static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx, static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); /* TODO(hongyu): record rpc client stats and census_rpc_end_op here */ @@ -160,7 +160,7 @@ static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx, static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); /* TODO(hongyu): record rpc server stats and census_tracing_end_op here */ diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c index bf64f84772..960d00e815 100644 --- a/src/core/ext/client_channel/client_channel.c +++ b/src/core/ext/client_channel/client_channel.c @@ -71,7 +71,8 @@ */ typedef enum { - WAIT_FOR_READY_UNSET, + /* zero so it can be default initialized */ + WAIT_FOR_READY_UNSET = 0, WAIT_FOR_READY_FALSE, WAIT_FOR_READY_TRUE } wait_for_ready_value; @@ -631,7 +632,8 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx, #define CANCELLED_CALL ((grpc_subchannel_call *)1) typedef enum { - GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING, + /* zero so that it can be default-initialized */ + GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0, GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL } subchannel_creation_phase; @@ -653,13 +655,13 @@ typedef struct client_channel_call_data { gpr_timespec call_start_time; gpr_timespec deadline; method_parameters *method_params; - grpc_closure read_service_config; grpc_error *cancel_error; /** either 0 for no call, 1 for cancelled, or a pointer to a grpc_subchannel_call */ gpr_atm subchannel_call; + gpr_arena *arena; subchannel_creation_phase creation_phase; grpc_connected_subchannel *connected_subchannel; @@ -726,6 +728,47 @@ static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) { gpr_free(ops); } +// Sets calld->method_params. +// If the method params specify a timeout, populates +// *per_method_deadline and returns true. +static bool set_call_method_params_from_service_config_locked( + grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + gpr_timespec *per_method_deadline) { + channel_data *chand = elem->channel_data; + call_data *calld = elem->call_data; + if (chand->method_params_table != NULL) { + calld->method_params = grpc_method_config_table_get( + exec_ctx, chand->method_params_table, calld->path); + if (calld->method_params != NULL) { + method_parameters_ref(calld->method_params); + if (gpr_time_cmp(calld->method_params->timeout, + gpr_time_0(GPR_TIMESPAN)) != 0) { + *per_method_deadline = + gpr_time_add(calld->call_start_time, calld->method_params->timeout); + return true; + } + } + } + return false; +} + +static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem) { + /* apply service-config level configuration to the call (now that we're + * certain it exists) */ + call_data *calld = elem->call_data; + gpr_timespec per_method_deadline; + if (set_call_method_params_from_service_config_locked(exec_ctx, elem, + &per_method_deadline)) { + // If the deadline from the service config is shorter than the one + // from the client API, reset the deadline timer. + if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) { + calld->deadline = per_method_deadline; + grpc_deadline_state_reset(exec_ctx, elem, calld->deadline); + } + } +} + static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element *elem = arg; @@ -754,9 +797,14 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg, } else { /* Create call on subchannel. */ grpc_subchannel_call *subchannel_call = NULL; + const grpc_connected_subchannel_call_args call_args = { + .pollent = calld->pollent, + .path = calld->path, + .start_time = calld->call_start_time, + .deadline = calld->deadline, + .arena = calld->arena}; grpc_error *new_error = grpc_connected_subchannel_create_call( - exec_ctx, calld->connected_subchannel, calld->pollent, calld->path, - calld->call_start_time, calld->deadline, &subchannel_call); + exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call); if (new_error != GRPC_ERROR_NONE) { new_error = grpc_error_add_child(new_error, error); subchannel_call = CANCELLED_CALL; @@ -851,6 +899,7 @@ static bool pick_subchannel_locked( } GPR_ASSERT(error == GRPC_ERROR_NONE); if (chand->lb_policy != NULL) { + apply_final_configuration_locked(exec_ctx, elem); grpc_lb_policy *lb_policy = chand->lb_policy; GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel"); // If the application explicitly set wait_for_ready, use that. @@ -982,9 +1031,14 @@ static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx, if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING && calld->connected_subchannel != NULL) { grpc_subchannel_call *subchannel_call = NULL; + const grpc_connected_subchannel_call_args call_args = { + .pollent = calld->pollent, + .path = calld->path, + .start_time = calld->call_start_time, + .deadline = calld->deadline, + .arena = calld->arena}; grpc_error *error = grpc_connected_subchannel_create_call( - exec_ctx, calld->connected_subchannel, calld->pollent, calld->path, - calld->call_start_time, calld->deadline, &subchannel_call); + exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call); if (error != GRPC_ERROR_NONE) { subchannel_call = CANCELLED_CALL; fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error)); @@ -1060,114 +1114,19 @@ static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx, GPR_TIMER_END("cc_start_transport_stream_op", 0); } -// Sets calld->method_params. -// If the method params specify a timeout, populates -// *per_method_deadline and returns true. -static bool set_call_method_params_from_service_config_locked( - grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - gpr_timespec *per_method_deadline) { - channel_data *chand = elem->channel_data; - call_data *calld = elem->call_data; - if (chand->method_params_table != NULL) { - calld->method_params = grpc_method_config_table_get( - exec_ctx, chand->method_params_table, calld->path); - if (calld->method_params != NULL) { - method_parameters_ref(calld->method_params); - if (gpr_time_cmp(calld->method_params->timeout, - gpr_time_0(GPR_TIMESPAN)) != 0) { - *per_method_deadline = - gpr_time_add(calld->call_start_time, calld->method_params->timeout); - return true; - } - } - } - return false; -} - -// Gets data from the service config. Invoked when the resolver returns -// its initial result. -static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_call_element *elem = arg; - call_data *calld = elem->call_data; - // If this is an error, there's no point in looking at the service config. - if (error == GRPC_ERROR_NONE) { - gpr_timespec per_method_deadline; - if (set_call_method_params_from_service_config_locked( - exec_ctx, elem, &per_method_deadline)) { - // If the deadline from the service config is shorter than the one - // from the client API, reset the deadline timer. - if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) { - calld->deadline = per_method_deadline; - grpc_deadline_state_reset(exec_ctx, elem, calld->deadline); - } - } - } - GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config"); -} - -static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx, - void *arg, - grpc_error *error_ignored) { - grpc_call_element *elem = arg; - channel_data *chand = elem->channel_data; - call_data *calld = elem->call_data; - // If the resolver has already returned results, then we can access - // the service config parameters immediately. Otherwise, we need to - // defer that work until the resolver returns an initial result. - if (chand->lb_policy != NULL) { - // We already have a resolver result, so check for service config. - gpr_timespec per_method_deadline; - if (set_call_method_params_from_service_config_locked( - exec_ctx, elem, &per_method_deadline)) { - calld->deadline = gpr_time_min(calld->deadline, per_method_deadline); - } - } else { - // We don't yet have a resolver result, so register a callback to - // get the service config data once the resolver returns. - // Take a reference to the call stack to be owned by the callback. - GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config"); - grpc_closure_init(&calld->read_service_config, read_service_config_locked, - elem, grpc_combiner_scheduler(chand->combiner, false)); - grpc_closure_list_append(&chand->waiting_for_config_closures, - &calld->read_service_config, GRPC_ERROR_NONE); - } - // Start the deadline timer with the current deadline value. If we - // do not yet have service config data, then the timer may be reset - // later. - grpc_deadline_state_start(exec_ctx, elem, calld->deadline); - GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, - "initial_read_service_config"); -} - /* Constructor for call_data */ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { - channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; // Initialize data members. grpc_deadline_state_init(exec_ctx, elem, args->call_stack); calld->path = grpc_slice_ref_internal(args->path); calld->call_start_time = args->start_time; calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC); - calld->method_params = NULL; - calld->cancel_error = GRPC_ERROR_NONE; - gpr_atm_rel_store(&calld->subchannel_call, 0); - calld->connected_subchannel = NULL; - calld->waiting_ops = NULL; - calld->waiting_ops_count = 0; - calld->waiting_ops_capacity = 0; - calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; calld->owning_call = args->call_stack; - calld->pollent = NULL; - GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config"); - grpc_closure_sched( - exec_ctx, - grpc_closure_init(&calld->read_service_config, - initial_read_service_config_locked, elem, - grpc_combiner_scheduler(chand->combiner, false)), - GRPC_ERROR_NONE); + calld->arena = args->arena; + grpc_deadline_state_start(exec_ctx, elem, calld->deadline); return GRPC_ERROR_NONE; } @@ -1175,7 +1134,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *and_free_memory) { + grpc_closure *then_schedule_closure) { call_data *calld = elem->call_data; grpc_deadline_state_destroy(exec_ctx, elem); grpc_slice_unref_internal(exec_ctx, calld->path); @@ -1185,6 +1144,8 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, GRPC_ERROR_UNREF(calld->cancel_error); grpc_subchannel_call *call = GET_CALL(calld); if (call != NULL && call != CANCELLED_CALL) { + grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure); + then_schedule_closure = NULL; GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); } GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING); @@ -1194,7 +1155,7 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, "picked"); } gpr_free(calld->waiting_ops); - gpr_free(and_free_memory); + grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); } static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, diff --git a/src/core/ext/client_channel/parse_address.c b/src/core/ext/client_channel/parse_address.c index 8ae15fc72b..cd1b2cd80c 100644 --- a/src/core/ext/client_channel/parse_address.c +++ b/src/core/ext/client_channel/parse_address.c @@ -128,6 +128,7 @@ int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) { GPR_ASSERT(host_end >= host); char host_without_scope[INET6_ADDRSTRLEN]; size_t host_without_scope_len = (size_t)(host_end - host); + uint32_t sin6_scope_id = 0; strncpy(host_without_scope, host, host_without_scope_len); host_without_scope[host_without_scope_len] = '\0'; if (inet_pton(AF_INET6, host_without_scope, &in6->sin6_addr) == 0) { @@ -136,10 +137,12 @@ int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) { } if (gpr_parse_bytes_to_uint32(host_end + 1, strlen(host) - host_without_scope_len - 1, - &in6->sin6_scope_id) == 0) { + &sin6_scope_id) == 0) { gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1); goto done; } + // Handle "sin6_scope_id" being type "u_long". See grpc issue ##10027. + in6->sin6_scope_id = sin6_scope_id; } else { if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) { gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host); diff --git a/src/core/ext/client_channel/proxy_mapper_registry.c b/src/core/ext/client_channel/proxy_mapper_registry.c index 2c44b9d490..0935ddbdbd 100644 --- a/src/core/ext/client_channel/proxy_mapper_registry.c +++ b/src/core/ext/client_channel/proxy_mapper_registry.c @@ -94,6 +94,14 @@ static void grpc_proxy_mapper_list_destroy(grpc_proxy_mapper_list* list) { grpc_proxy_mapper_destroy(list->list[i]); } gpr_free(list->list); + // Clean up in case we re-initialze later. + // TODO(ctiller): This should ideally live in + // grpc_proxy_mapper_registry_init(). However, if we did this there, + // then we would do it AFTER we start registering proxy mappers from + // third-party plugins, so they'd never show up (and would leak memory). + // We probably need some sort of dependency system for plugins to fix + // this. + memset(list, 0, sizeof(*list)); } // @@ -102,9 +110,7 @@ static void grpc_proxy_mapper_list_destroy(grpc_proxy_mapper_list* list) { static grpc_proxy_mapper_list g_proxy_mapper_list; -void grpc_proxy_mapper_registry_init() { - memset(&g_proxy_mapper_list, 0, sizeof(g_proxy_mapper_list)); -} +void grpc_proxy_mapper_registry_init() {} void grpc_proxy_mapper_registry_shutdown() { grpc_proxy_mapper_list_destroy(&g_proxy_mapper_list); diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c index 5df0a9060d..ed5029ea9a 100644 --- a/src/core/ext/client_channel/subchannel.c +++ b/src/core/ext/client_channel/subchannel.c @@ -148,6 +148,7 @@ struct grpc_subchannel { struct grpc_subchannel_call { grpc_connected_subchannel *connection; + grpc_closure *schedule_closure_after_destroy; }; #define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1)) @@ -340,17 +341,15 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, GPR_ASSERT(new_address != NULL); gpr_free(addr); addr = new_address; - if (new_args != NULL) c->args = new_args; - } - if (c->args == NULL) { - static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; - grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); - c->args = grpc_channel_args_copy_and_add_and_remove( - args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, - 1); - gpr_free(new_arg.value.string); } + static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; + grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); gpr_free(addr); + c->args = grpc_channel_args_copy_and_add_and_remove( + new_args != NULL ? new_args : args->args, keys_to_remove, + GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1); + gpr_free(new_arg.value.string); + if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args); c->root_external_state_watcher.next = c->root_external_state_watcher.prev = &c->root_external_state_watcher; grpc_closure_init(&c->connected, subchannel_connected, c, @@ -719,13 +718,22 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg, static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { grpc_subchannel_call *c = call; + GPR_ASSERT(c->schedule_closure_after_destroy != NULL); GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0); grpc_connected_subchannel *connection = c->connection; - grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), NULL, c); + grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), NULL, + c->schedule_closure_after_destroy); GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, connection, "subchannel_call"); GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0); } +void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call *call, + grpc_closure *closure) { + GPR_ASSERT(call->schedule_closure_after_destroy == NULL); + GPR_ASSERT(closure != NULL); + call->schedule_closure_after_destroy = closure; +} + void grpc_subchannel_call_ref( grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); @@ -761,15 +769,22 @@ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel( grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, - grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time, - gpr_timespec deadline, grpc_subchannel_call **call) { + const grpc_connected_subchannel_call_args *args, + grpc_subchannel_call **call) { grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con); - *call = gpr_zalloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); + *call = gpr_arena_alloc( + args->arena, sizeof(grpc_subchannel_call) + chanstk->call_stack_size); grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); (*call)->connection = con; // Ref is added below. - grpc_error *error = - grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, *call, - NULL, NULL, path, start_time, deadline, callstk); + const grpc_call_element_args call_args = {.call_stack = callstk, + .server_transport_data = NULL, + .context = NULL, + .path = args->path, + .start_time = args->start_time, + .deadline = args->deadline, + .arena = args->arena}; + grpc_error *error = grpc_call_stack_init( + exec_ctx, chanstk, 1, subchannel_call_destroy, *call, &call_args); if (error != GRPC_ERROR_NONE) { const char *error_string = grpc_error_string(error); gpr_log(GPR_ERROR, "error: %s", error_string); @@ -778,7 +793,7 @@ grpc_error *grpc_connected_subchannel_create_call( return error; } GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call"); - grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, pollent); + grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, args->pollent); return GRPC_ERROR_NONE; } diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h index 6a70a76467..3e64a2507c 100644 --- a/src/core/ext/client_channel/subchannel.h +++ b/src/core/ext/client_channel/subchannel.h @@ -37,6 +37,7 @@ #include "src/core/ext/client_channel/connector.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/support/arena.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" @@ -112,10 +113,18 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx, GRPC_SUBCHANNEL_REF_EXTRA_ARGS); /** construct a subchannel call */ +typedef struct { + grpc_polling_entity *pollent; + grpc_slice path; + gpr_timespec start_time; + gpr_timespec deadline; + gpr_arena *arena; +} grpc_connected_subchannel_call_args; + grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel, - grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time, - gpr_timespec deadline, grpc_subchannel_call **subchannel_call); + const grpc_connected_subchannel_call_args *args, + grpc_subchannel_call **subchannel_call); /** process a transport level op */ void grpc_connected_subchannel_process_transport_op( @@ -154,6 +163,11 @@ void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx, char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *subchannel_call); +/** Must be called once per call. Sets the 'then_schedule_closure' argument for + call stack destruction. */ +void grpc_subchannel_call_set_cleanup_closure( + grpc_subchannel_call *subchannel_call, grpc_closure *closure); + grpc_call_stack *grpc_subchannel_call_get_call_stack( grpc_subchannel_call *subchannel_call); diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c index c2750634a5..4ed832671d 100644 --- a/src/core/ext/load_reporting/load_reporting_filter.c +++ b/src/core/ext/load_reporting/load_reporting_filter.c @@ -123,7 +123,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { call_data *calld = elem->call_data; /* TODO(dgq): do something with the data diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index da4c7dc7b2..082078c72f 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -511,6 +511,10 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { if (!t->closed) { + if (!grpc_error_has_clear_grpc_status(error)) { + error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAVAILABLE); + } if (t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE) { if (t->close_transport_on_writes_finished == NULL) { t->close_transport_on_writes_finished = @@ -520,10 +524,6 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_error_add_child(t->close_transport_on_writes_finished, error); return; } - if (!grpc_error_has_clear_grpc_status(error)) { - error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_UNAVAILABLE); - } t->closed = 1; connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "close_transport"); @@ -575,7 +575,7 @@ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s) { static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_stream_refcount *refcount, - const void *server_data) { + const void *server_data, gpr_arena *arena) { GPR_TIMER_BEGIN("init_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; @@ -588,8 +588,8 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, gpr_ref_init(&s->active_streams, 1); GRPC_CHTTP2_STREAM_REF(s, "chttp2"); - grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0]); - grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1]); + grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0], arena); + grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1], arena); grpc_chttp2_data_parser_init(&s->data_parser); grpc_slice_buffer_init(&s->flow_controlled_buffer); s->deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); @@ -665,16 +665,17 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, GPR_TIMER_END("destroy_stream", 0); - gpr_free(s->destroy_stream_arg); + grpc_closure_sched(exec_ctx, s->destroy_stream_arg, GRPC_ERROR_NONE); } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, void *and_free_memory) { + grpc_stream *gs, + grpc_closure *then_schedule_closure) { GPR_TIMER_BEGIN("destroy_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - s->destroy_stream_arg = and_free_memory; + s->destroy_stream_arg = then_schedule_closure; grpc_closure_sched( exec_ctx, grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s, grpc_combiner_scheduler(t->combiner, false)), @@ -1629,15 +1630,19 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, s->recv_trailing_metadata_finished != NULL) { char status_string[GPR_LTOA_MIN_BUFSIZE]; gpr_ltoa(status, status_string); - grpc_chttp2_incoming_metadata_buffer_replace_or_add( - exec_ctx, &s->metadata_buffer[1], - grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS, - grpc_slice_from_copied_string(status_string))); + GRPC_LOG_IF_ERROR("add_status", + grpc_chttp2_incoming_metadata_buffer_replace_or_add( + exec_ctx, &s->metadata_buffer[1], + grpc_mdelem_from_slices( + exec_ctx, GRPC_MDSTR_GRPC_STATUS, + grpc_slice_from_copied_string(status_string)))); if (msg != NULL) { - grpc_chttp2_incoming_metadata_buffer_replace_or_add( - exec_ctx, &s->metadata_buffer[1], - grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, - grpc_slice_from_copied_string(msg))); + GRPC_LOG_IF_ERROR( + "add_status_message", + grpc_chttp2_incoming_metadata_buffer_replace_or_add( + exec_ctx, &s->metadata_buffer[1], + grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, + grpc_slice_from_copied_string(msg)))); } s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.c b/src/core/ext/transport/chttp2/transport/frame_ping.c index f487533c41..9b4b1a7b84 100644 --- a/src/core/ext/transport/chttp2/transport/frame_ping.c +++ b/src/core/ext/transport/chttp2/transport/frame_ping.c @@ -91,7 +91,7 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_ping_parser *p = parser; while (p->byte != 8 && cur != end) { - p->opaque_8bytes |= (((uint64_t)*cur) << (8 * p->byte)); + p->opaque_8bytes |= (((uint64_t)*cur) << (56 - 8 * p->byte)); cur++; p->byte++; } diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c index 40f5120308..1865b997b7 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.c +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c @@ -1620,13 +1620,18 @@ void grpc_chttp2_hpack_parser_destroy(grpc_exec_ctx *exec_ctx, grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, grpc_slice slice) { - /* TODO(ctiller): limit the distance of end from beg, and perform multiple - steps in the event of a large chunk of data to limit - stack space usage when no tail call optimization is - available */ +/* max number of bytes to parse at a time... limits call stack depth on + * compilers without TCO */ +#define MAX_PARSE_LENGTH 1024 p->current_slice_refcount = slice.refcount; - grpc_error *error = p->state(exec_ctx, p, GRPC_SLICE_START_PTR(slice), - GRPC_SLICE_END_PTR(slice)); + uint8_t *start = GRPC_SLICE_START_PTR(slice); + uint8_t *end = GRPC_SLICE_END_PTR(slice); + grpc_error *error = GRPC_ERROR_NONE; + while (start != end && error == GRPC_ERROR_NONE) { + uint8_t *target = start + GPR_MIN(MAX_PARSE_LENGTH, end - start); + error = p->state(exec_ctx, p, start, target); + start = target; + } p->current_slice_refcount = NULL; return error; } diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.c b/src/core/ext/transport/chttp2/transport/incoming_metadata.c index c91b019aa0..da0a34d32a 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.c +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.c @@ -41,69 +41,48 @@ #include <grpc/support/log.h> void grpc_chttp2_incoming_metadata_buffer_init( - grpc_chttp2_incoming_metadata_buffer *buffer) { - buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); + grpc_chttp2_incoming_metadata_buffer *buffer, gpr_arena *arena) { + buffer->arena = arena; + grpc_metadata_batch_init(&buffer->batch); + buffer->batch.deadline = gpr_inf_future(GPR_CLOCK_REALTIME); } void grpc_chttp2_incoming_metadata_buffer_destroy( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer) { - size_t i; - if (!buffer->published) { - for (i = 0; i < buffer->count; i++) { - GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md); - } - } - gpr_free(buffer->elems); + grpc_metadata_batch_destroy(exec_ctx, &buffer->batch); } -void grpc_chttp2_incoming_metadata_buffer_add( - grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) { - GPR_ASSERT(!buffer->published); - if (buffer->capacity == buffer->count) { - buffer->capacity = GPR_MAX(8, 2 * buffer->capacity); - buffer->elems = - gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity); - } - buffer->elems[buffer->count++].md = elem; +grpc_error *grpc_chttp2_incoming_metadata_buffer_add( + grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, + grpc_mdelem elem) { buffer->size += GRPC_MDELEM_LENGTH(elem); + return grpc_metadata_batch_add_tail( + exec_ctx, &buffer->batch, + gpr_arena_alloc(buffer->arena, sizeof(grpc_linked_mdelem)), elem); } -void grpc_chttp2_incoming_metadata_buffer_replace_or_add( +grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) { - for (size_t i = 0; i < buffer->count; i++) { - if (grpc_slice_eq(GRPC_MDKEY(buffer->elems[i].md), GRPC_MDKEY(elem))) { - GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md); - buffer->elems[i].md = elem; - return; + for (grpc_linked_mdelem *l = buffer->batch.list.head; l != NULL; + l = l->next) { + if (grpc_slice_eq(GRPC_MDKEY(l->md), GRPC_MDKEY(elem))) { + GRPC_MDELEM_UNREF(exec_ctx, l->md); + l->md = elem; + return GRPC_ERROR_NONE; } } - grpc_chttp2_incoming_metadata_buffer_add(buffer, elem); + return grpc_chttp2_incoming_metadata_buffer_add(exec_ctx, buffer, elem); } void grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) { - GPR_ASSERT(!buffer->published); - buffer->deadline = deadline; + buffer->batch.deadline = deadline; } void grpc_chttp2_incoming_metadata_buffer_publish( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) { - GPR_ASSERT(!buffer->published); - buffer->published = 1; - if (buffer->count > 0) { - size_t i; - for (i = 0; i < buffer->count; i++) { - /* TODO(ctiller): do something better here */ - if (!GRPC_LOG_IF_ERROR("grpc_chttp2_incoming_metadata_buffer_publish", - grpc_metadata_batch_link_tail( - exec_ctx, batch, &buffer->elems[i]))) { - GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md); - } - } - } else { - batch->list.head = batch->list.tail = NULL; - } - batch->deadline = buffer->deadline; + *batch = buffer->batch; + grpc_metadata_batch_init(&buffer->batch); } diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h index 1eac6fc150..288c917e65 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.h +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.h @@ -37,28 +37,26 @@ #include "src/core/lib/transport/transport.h" typedef struct { - grpc_linked_mdelem *elems; - size_t count; - size_t capacity; - gpr_timespec deadline; - int published; + gpr_arena *arena; + grpc_metadata_batch batch; size_t size; // total size of metadata } grpc_chttp2_incoming_metadata_buffer; /** assumes everything initially zeroed */ void grpc_chttp2_incoming_metadata_buffer_init( - grpc_chttp2_incoming_metadata_buffer *buffer); + grpc_chttp2_incoming_metadata_buffer *buffer, gpr_arena *arena); void grpc_chttp2_incoming_metadata_buffer_destroy( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer); void grpc_chttp2_incoming_metadata_buffer_publish( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch); -void grpc_chttp2_incoming_metadata_buffer_add( - grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem); -void grpc_chttp2_incoming_metadata_buffer_replace_or_add( +grpc_error *grpc_chttp2_incoming_metadata_buffer_add( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, - grpc_mdelem elem); + grpc_mdelem elem) GRPC_MUST_USE_RESULT; +grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add( + grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, + grpc_mdelem elem) GRPC_MUST_USE_RESULT; void grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index d26812ad6b..3c56c21599 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -425,7 +425,7 @@ struct grpc_chttp2_stream { grpc_stream_refcount *refcount; grpc_closure destroy_stream; - void *destroy_stream_arg; + grpc_closure *destroy_stream_arg; grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; uint8_t included[STREAM_LIST_COUNT]; diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 7ed00522c3..7efc8c63c9 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -381,16 +381,38 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx, s->incoming_window_delta + t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) { - char *msg; - gpr_asprintf(&msg, - "frame of size %d overflows incoming window of %" PRId64, - t->incoming_frame_size, - s->incoming_window_delta + - t->settings[GRPC_ACKED_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); - grpc_error *err = GRPC_ERROR_CREATE(msg); - gpr_free(msg); - return err; + if (incoming_frame_size <= + s->incoming_window_delta + + t->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) { + gpr_log( + GPR_ERROR, + "Incoming frame of size %d exceeds incoming window size of %" PRId64 + ".\n" + "The (un-acked, future) window size would be %" PRId64 + " which is not exceeded.\n" + "This would usually cause a disconnection, but allowing it due to " + "broken HTTP2 implementations in the wild.\n" + "See (for example) https://github.com/netty/netty/issues/6520.", + t->incoming_frame_size, + s->incoming_window_delta + + t->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + s->incoming_window_delta + + t->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); + } else { + char *msg; + gpr_asprintf(&msg, + "frame of size %d overflows incoming window of %" PRId64, + t->incoming_frame_size, + s->incoming_window_delta + + t->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); + grpc_error *err = GRPC_ERROR_CREATE(msg); + gpr_free(msg); + return err; + } } GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s, @@ -526,7 +548,14 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp, s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } else { - grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md); + grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add( + exec_ctx, &s->metadata_buffer[0], md); + if (error != GRPC_ERROR_NONE) { + grpc_chttp2_cancel_stream(exec_ctx, t, s, error); + grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); + s->seen_error = true; + GRPC_MDELEM_UNREF(exec_ctx, md); + } } } @@ -576,7 +605,14 @@ static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp, s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } else { - grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[1], md); + grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add( + exec_ctx, &s->metadata_buffer[1], md); + if (error != GRPC_ERROR_NONE) { + grpc_chttp2_cancel_stream(exec_ctx, t, s, error); + grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); + s->seen_error = true; + GRPC_MDELEM_UNREF(exec_ctx, md); + } } GPR_TIMER_END("on_trailing_header", 0); diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index 01a03533da..450d9ab23a 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -54,6 +54,7 @@ #include "third_party/objective_c/Cronet/bidirectional_stream_c.h" #define GRPC_HEADER_SIZE_IN_BYTES 5 +#define GRPC_FLUSH_READ_SIZE 4096 #define CRONET_LOG(...) \ do { \ @@ -151,11 +152,17 @@ struct write_state { struct op_state { bool state_op_done[OP_NUM_OPS]; bool state_callback_received[OP_NUM_OPS]; + /* A non-zero gRPC status code has been seen */ bool fail_state; + /* Transport is discarding all buffered messages */ bool flush_read; bool flush_cronet_when_ready; bool pending_write_for_trailer; - bool unprocessed_send_message; + bool pending_send_message; + /* User requested RECV_TRAILING_METADATA */ + bool pending_recv_trailing_metadata; + /* Cronet has not issued a callback of a bidirectional read */ + bool pending_read_from_cronet; grpc_error *cancel_error; /* data structure for storing data coming from server */ struct read_state rs; @@ -177,6 +184,7 @@ struct op_storage { }; struct stream_obj { + gpr_arena *arena; struct op_and_state *oas; grpc_transport_stream_op *curr_op; grpc_cronet_transport *curr_ct; @@ -248,11 +256,35 @@ static const char *op_id_string(enum e_op_id i) { return "UNKNOWN"; } -static void free_read_buffer(stream_obj *s) { +static void null_and_maybe_free_read_buffer(stream_obj *s) { if (s->state.rs.read_buffer && s->state.rs.read_buffer != s->state.rs.grpc_header_bytes) { gpr_free(s->state.rs.read_buffer); - s->state.rs.read_buffer = NULL; + } + s->state.rs.read_buffer = NULL; +} + +static void maybe_flush_read(stream_obj *s) { + /* To enter flush read state (discarding all the buffered messages in + * transport layer), two conditions must be satisfied: 1) non-zero grpc status + * has been received, and 2) an op requesting the status code + * (RECV_TRAILING_METADATA) is issued by the user. (See + * doc/status_ordering.md) */ + /* Whenever the evaluation of any of the two condition is changed, we check + * whether we should enter the flush read state. */ + if (s->state.pending_recv_trailing_metadata && s->state.fail_state) { + if (!s->state.flush_read && !s->state.rs.read_stream_closed) { + CRONET_LOG(GPR_DEBUG, "%p: Flush read", s); + s->state.flush_read = true; + null_and_maybe_free_read_buffer(s); + s->state.rs.read_buffer = gpr_malloc(GRPC_FLUSH_READ_SIZE); + if (!s->state.pending_read_from_cronet) { + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); + bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, + GRPC_FLUSH_READ_SIZE); + s->state.pending_read_from_cronet = true; + } + } } } @@ -279,7 +311,11 @@ static void add_to_storage(struct stream_obj *s, grpc_transport_stream_op *op) { storage->head = new_op; storage->num_pending_ops++; if (op->send_message) { - s->state.unprocessed_send_message = true; + s->state.pending_send_message = true; + } + if (op->recv_trailing_metadata) { + s->state.pending_recv_trailing_metadata = true; + maybe_flush_read(s); } CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op, storage->num_pending_ops); @@ -367,7 +403,7 @@ static void on_failed(bidirectional_stream *stream, int net_error) { gpr_free(s->state.ws.write_buffer); s->state.ws.write_buffer = NULL; } - free_read_buffer(s); + null_and_maybe_free_read_buffer(s); gpr_mu_unlock(&s->mu); execute_from_storage(s); } @@ -390,7 +426,7 @@ static void on_canceled(bidirectional_stream *stream) { gpr_free(s->state.ws.write_buffer); s->state.ws.write_buffer = NULL; } - free_read_buffer(s); + null_and_maybe_free_read_buffer(s); gpr_mu_unlock(&s->mu); execute_from_storage(s); } @@ -405,7 +441,7 @@ static void on_succeeded(bidirectional_stream *stream) { bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_SUCCEEDED] = true; s->cbs = NULL; - free_read_buffer(s); + null_and_maybe_free_read_buffer(s); gpr_mu_unlock(&s->mu); execute_from_storage(s); } @@ -451,15 +487,18 @@ static void on_response_headers_received( gpr_mu_lock(&s->mu); memset(&s->state.rs.initial_metadata, 0, sizeof(s->state.rs.initial_metadata)); - grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata); + grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata, + s->arena); for (size_t i = 0; i < headers->count; i++) { - grpc_chttp2_incoming_metadata_buffer_add( - &s->state.rs.initial_metadata, - grpc_mdelem_from_slices( - &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( - headers->headers[i].key)), - grpc_slice_intern( - grpc_slice_from_static_string(headers->headers[i].value)))); + GRPC_LOG_IF_ERROR( + "on_response_headers_received", + grpc_chttp2_incoming_metadata_buffer_add( + &exec_ctx, &s->state.rs.initial_metadata, + grpc_mdelem_from_slices( + &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( + headers->headers[i].key)), + grpc_slice_intern(grpc_slice_from_static_string( + headers->headers[i].value))))); } s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true; if (!(s->state.state_op_done[OP_CANCEL_ERROR] || @@ -473,6 +512,7 @@ static void on_response_headers_received( CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, s->state.rs.remaining_bytes); + s->state.pending_read_from_cronet = true; } gpr_mu_unlock(&s->mu); grpc_exec_ctx_finish(&exec_ctx); @@ -504,10 +544,13 @@ static void on_read_completed(bidirectional_stream *stream, char *data, CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data, count); gpr_mu_lock(&s->mu); + s->state.pending_read_from_cronet = false; s->state.state_callback_received[OP_RECV_MESSAGE] = true; if (count > 0 && s->state.flush_read) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); - bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, 4096); + bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, + GRPC_FLUSH_READ_SIZE); + s->state.pending_read_from_cronet = true; gpr_mu_unlock(&s->mu); } else if (count > 0) { s->state.rs.received_bytes += count; @@ -518,16 +561,14 @@ static void on_read_completed(bidirectional_stream *stream, char *data, bidirectional_stream_read( s->cbs, s->state.rs.read_buffer + s->state.rs.received_bytes, s->state.rs.remaining_bytes); + s->state.pending_read_from_cronet = true; gpr_mu_unlock(&s->mu); } else { gpr_mu_unlock(&s->mu); execute_from_storage(s); } } else { - if (s->state.flush_read) { - gpr_free(s->state.rs.read_buffer); - s->state.rs.read_buffer = NULL; - } + null_and_maybe_free_read_buffer(s); s->state.rs.read_stream_closed = true; gpr_mu_unlock(&s->mu); execute_from_storage(s); @@ -549,21 +590,25 @@ static void on_response_trailers_received( memset(&s->state.rs.trailing_metadata, 0, sizeof(s->state.rs.trailing_metadata)); s->state.rs.trailing_metadata_valid = false; - grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.trailing_metadata); + grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.trailing_metadata, + s->arena); for (size_t i = 0; i < trailers->count; i++) { CRONET_LOG(GPR_DEBUG, "trailer key=%s, value=%s", trailers->headers[i].key, trailers->headers[i].value); - grpc_chttp2_incoming_metadata_buffer_add( - &s->state.rs.trailing_metadata, - grpc_mdelem_from_slices( - &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( - trailers->headers[i].key)), - grpc_slice_intern( - grpc_slice_from_static_string(trailers->headers[i].value)))); + GRPC_LOG_IF_ERROR( + "on_response_trailers_received", + grpc_chttp2_incoming_metadata_buffer_add( + &exec_ctx, &s->state.rs.trailing_metadata, + grpc_mdelem_from_slices( + &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( + trailers->headers[i].key)), + grpc_slice_intern(grpc_slice_from_static_string( + trailers->headers[i].value))))); s->state.rs.trailing_metadata_valid = true; if (0 == strcmp(trailers->headers[i].key, "grpc-status") && 0 != strcmp(trailers->headers[i].value, "0")) { s->state.fail_state = true; + maybe_flush_read(s); } } s->state.state_callback_received[OP_RECV_TRAILING_METADATA] = true; @@ -778,7 +823,7 @@ static bool op_can_be_run(grpc_transport_stream_op *curr_op, else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) result = false; /* we haven't sent message yet */ - else if (stream_state->unprocessed_send_message && + else if (stream_state->pending_send_message && !stream_state->state_op_done[OP_SEND_MESSAGE]) result = false; /* we haven't got on_write_completed for the send yet */ @@ -900,7 +945,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, } else if (stream_op->send_message && op_can_be_run(stream_op, s, &oas->state, OP_SEND_MESSAGE)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas); - stream_state->unprocessed_send_message = false; + stream_state->pending_send_message = false; if (stream_state->state_callback_received[OP_FAILED]) { result = NO_ACTION_POSSIBLE; CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); @@ -1009,6 +1054,13 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; result = ACTION_TAKEN_NO_CALLBACK; + } else if (stream_state->flush_read) { + CRONET_LOG(GPR_DEBUG, "flush read"); + grpc_closure_sched(exec_ctx, stream_op->recv_message_ready, + GRPC_ERROR_NONE); + stream_state->state_op_done[OP_RECV_MESSAGE] = true; + oas->state.state_op_done[OP_RECV_MESSAGE] = true; + result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_state->rs.length_field_received == false) { if (stream_state->rs.received_bytes == GRPC_HEADER_SIZE_IN_BYTES && stream_state->rs.remaining_bytes == 0) { @@ -1029,6 +1081,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, true; /* Indicates that at least one read request has been made */ bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); + stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_WITH_CALLBACK; } else { stream_state->rs.remaining_bytes = 0; @@ -1047,11 +1100,13 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; stream_state->rs.received_bytes = 0; + stream_state->rs.length_field_received = false; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); stream_state->state_op_done[OP_READ_REQ_MADE] = true; /* Indicates that at least one read request has been made */ bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); + stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_NO_CALLBACK; } } else if (stream_state->rs.remaining_bytes == 0) { @@ -1064,6 +1119,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, true; /* Indicates that at least one read request has been made */ bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); + stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_WITH_CALLBACK; } else { result = NO_ACTION_POSSIBLE; @@ -1075,7 +1131,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, uint8_t *dst_p = GRPC_SLICE_START_PTR(read_data_slice); memcpy(dst_p, stream_state->rs.read_buffer, (size_t)stream_state->rs.length_field); - free_read_buffer(s); + null_and_maybe_free_read_buffer(s); grpc_slice_buffer_init(&stream_state->rs.read_slice_buffer); grpc_slice_buffer_add(&stream_state->rs.read_slice_buffer, read_data_slice); @@ -1096,6 +1152,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); + stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_NO_CALLBACK; } } else if (stream_op->recv_trailing_metadata && @@ -1153,15 +1210,6 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, make a note */ if (stream_op->recv_message) stream_state->state_op_done[OP_RECV_MESSAGE_AND_ON_COMPLETE] = true; - } else if (stream_state->fail_state && !stream_state->flush_read) { - CRONET_LOG(GPR_DEBUG, "running: %p flush read", oas); - if (stream_state->rs.read_buffer && - stream_state->rs.read_buffer != stream_state->rs.grpc_header_bytes) { - gpr_free(stream_state->rs.read_buffer); - stream_state->rs.read_buffer = NULL; - } - stream_state->rs.read_buffer = gpr_malloc(4096); - stream_state->flush_read = true; } else { result = NO_ACTION_POSSIBLE; } @@ -1174,7 +1222,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_stream_refcount *refcount, - const void *server_data) { + const void *server_data, gpr_arena *arena) { stream_obj *s = (stream_obj *)gs; memset(&s->storage, 0, sizeof(s->storage)); s->storage.head = NULL; @@ -1190,10 +1238,13 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, s->state.fail_state = s->state.flush_read = false; s->state.cancel_error = NULL; s->state.flush_cronet_when_ready = s->state.pending_write_for_trailer = false; - s->state.unprocessed_send_message = false; + s->state.pending_send_message = false; + s->state.pending_recv_trailing_metadata = false; + s->state.pending_read_from_cronet = false; s->curr_gs = gs; s->curr_ct = (grpc_cronet_transport *)gt; + s->arena = arena; gpr_mu_init(&s->mu); return 0; @@ -1209,38 +1260,33 @@ static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx, static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_transport_stream_op *op) { CRONET_LOG(GPR_DEBUG, "perform_stream_op"); - stream_obj *s = (stream_obj *)gs; - add_to_storage(s, op); if (op->send_initial_metadata && header_has_authority(op->send_initial_metadata->list.head)) { /* Cronet does not support :authority header field. We cancel the call when - this field is present in metadata */ - bidirectional_stream_header_array header_array; - bidirectional_stream_header *header; - bidirectional_stream cbs; - CRONET_LOG(GPR_DEBUG, - ":authority header is provided but not supported;" - " cancel operations"); - /* Notify application that operation is cancelled by forging trailers */ - header_array.count = 1; - header_array.capacity = 1; - header_array.headers = gpr_malloc(sizeof(bidirectional_stream_header)); - header = (bidirectional_stream_header *)header_array.headers; - header->key = "grpc-status"; - header->value = "1"; /* Return status GRPC_STATUS_CANCELLED */ - cbs.annotation = (void *)s; - s->state.state_op_done[OP_CANCEL_ERROR] = true; - on_response_trailers_received(&cbs, &header_array); - gpr_free(header_array.headers); - } else { - execute_from_storage(s); + this field is present in metadata */ + if (op->recv_initial_metadata_ready) { + grpc_closure_sched(exec_ctx, op->recv_initial_metadata_ready, + GRPC_ERROR_CANCELLED); + } + if (op->recv_message_ready) { + grpc_closure_sched(exec_ctx, op->recv_message_ready, + GRPC_ERROR_CANCELLED); + } + grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_CANCELLED); + return; } + stream_obj *s = (stream_obj *)gs; + add_to_storage(s, op); + execute_from_storage(s); } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, void *and_free_memory) { + grpc_stream *gs, + grpc_closure *then_schedule_closure) { stream_obj *s = (stream_obj *)gs; + null_and_maybe_free_read_buffer(s); GRPC_ERROR_UNREF(s->state.cancel_error); + grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); } static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {} diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index 3fb2a60ac7..6d53b0576e 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -166,41 +166,32 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, } } -grpc_error *grpc_call_stack_init( - grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, - int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, - grpc_call_context_element *context, const void *transport_server_data, - grpc_slice path, gpr_timespec start_time, gpr_timespec deadline, - grpc_call_stack *call_stack) { +grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, + grpc_channel_stack *channel_stack, + int initial_refs, grpc_iomgr_cb_func destroy, + void *destroy_arg, + const grpc_call_element_args *elem_args) { grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); size_t count = channel_stack->count; grpc_call_element *call_elems; char *user_data; size_t i; - call_stack->count = count; - GRPC_STREAM_REF_INIT(&call_stack->refcount, initial_refs, destroy, + elem_args->call_stack->count = count; + GRPC_STREAM_REF_INIT(&elem_args->call_stack->refcount, initial_refs, destroy, destroy_arg, "CALL_STACK"); - call_elems = CALL_ELEMS_FROM_STACK(call_stack); + call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack); user_data = ((char *)call_elems) + ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); /* init per-filter data */ grpc_error *first_error = GRPC_ERROR_NONE; - const grpc_call_element_args args = { - .start_time = start_time, - .call_stack = call_stack, - .server_transport_data = transport_server_data, - .context = context, - .path = path, - .deadline = deadline, - }; for (i = 0; i < count; i++) { call_elems[i].filter = channel_elems[i].filter; call_elems[i].channel_data = channel_elems[i].channel_data; call_elems[i].call_data = user_data; - grpc_error *error = - call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args); + grpc_error *error = call_elems[i].filter->init_call_elem( + exec_ctx, &call_elems[i], elem_args); if (error != GRPC_ERROR_NONE) { if (first_error == GRPC_ERROR_NONE) { first_error = error; @@ -241,15 +232,16 @@ void grpc_call_stack_ignore_set_pollset_or_pollset_set( void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, const grpc_call_final_info *final_info, - void *and_free_memory) { + grpc_closure *then_schedule_closure) { grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack); size_t count = stack->count; size_t i; /* destroy per-filter data */ for (i = 0; i < count; i++) { - elems[i].filter->destroy_call_elem(exec_ctx, &elems[i], final_info, - i == count - 1 ? and_free_memory : NULL); + elems[i].filter->destroy_call_elem( + exec_ctx, &elems[i], final_info, + i == count - 1 ? then_schedule_closure : NULL); } } diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 6d3340bcbf..80e3603e8d 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -56,6 +56,7 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/support/arena.h" #include "src/core/lib/transport/transport.h" #ifdef __cplusplus @@ -84,6 +85,7 @@ typedef struct { grpc_slice path; gpr_timespec start_time; gpr_timespec deadline; + gpr_arena *arena; } grpc_call_element_args; typedef struct { @@ -139,12 +141,12 @@ typedef struct { /* Destroy per call data. The filter does not need to do any chaining. The bottom filter of a stack will be passed a non-NULL pointer to - \a and_free_memory that should be passed to gpr_free when destruction - is complete. \a final_info contains data about the completed call, mainly - for reporting purposes. */ + \a then_schedule_closure that should be passed to grpc_closure_sched when + destruction is complete. \a final_info contains data about the completed + call, mainly for reporting purposes. */ void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *and_free_memory); + grpc_closure *then_schedule_closure); /* sizeof(per channel data) */ size_t sizeof_channel_data; @@ -236,12 +238,11 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, /* Initialize a call stack given a channel stack. transport_server_data is expected to be NULL on a client, or an opaque transport owned pointer on the server. */ -grpc_error *grpc_call_stack_init( - grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, - int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, - grpc_call_context_element *context, const void *transport_server_data, - grpc_slice path, gpr_timespec start_time, gpr_timespec deadline, - grpc_call_stack *call_stack); +grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, + grpc_channel_stack *channel_stack, + int initial_refs, grpc_iomgr_cb_func destroy, + void *destroy_arg, + const grpc_call_element_args *elem_args); /* Set a pollset or a pollset_set for a call stack: must occur before the first * op is started */ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, @@ -271,7 +272,7 @@ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, /* Destroy a call stack */ void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, const grpc_call_final_info *final_info, - void *and_free_memory); + grpc_closure *then_schedule_closure); /* Ignore set pollset{_set} - used by filters if they don't care about pollsets * at all. Does nothing. */ diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c index aa41014a21..02dc479f3a 100644 --- a/src/core/lib/channel/compress_filter.c +++ b/src/core/lib/channel/compress_filter.c @@ -292,7 +292,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); diff --git a/src/core/lib/channel/connected_channel.c b/src/core/lib/channel/connected_channel.c index 29796f7ca7..42ef7b7806 100644 --- a/src/core/lib/channel/connected_channel.c +++ b/src/core/lib/channel/connected_channel.c @@ -88,7 +88,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, channel_data *chand = elem->channel_data; int r = grpc_transport_init_stream( exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), - &args->call_stack->refcount, args->server_transport_data); + &args->call_stack->refcount, args->server_transport_data, args->arena); return r == 0 ? GRPC_ERROR_NONE : GRPC_ERROR_CREATE("transport stream initialization failed"); } @@ -105,12 +105,12 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *and_free_memory) { + grpc_closure *then_schedule_closure) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_transport_destroy_stream(exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), - and_free_memory); + then_schedule_closure); } /* Constructor for channel_data */ diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 5a12d62f1d..34114bbebf 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -256,7 +256,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, // Destructor for call_data. Used for both client and server filters. static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, - void* and_free_memory) { + grpc_closure* ignored) { grpc_deadline_state_destroy(exec_ctx, elem); } diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c index c031533dd8..f9d0d689ac 100644 --- a/src/core/lib/channel/http_client_filter.c +++ b/src/core/lib/channel/http_client_filter.c @@ -412,7 +412,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { call_data *calld = elem->call_data; grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); } diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c index fb70de8e96..bebd3af335 100644 --- a/src/core/lib/channel/http_server_filter.c +++ b/src/core/lib/channel/http_server_filter.c @@ -358,7 +358,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { call_data *calld = elem->call_data; grpc_slice_buffer_destroy_internal(exec_ctx, &calld->read_slice_buffer); } diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index b424c0d2ac..5ba13fe251 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -200,7 +200,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, // Destructor for call_data. static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, - void* ignored) {} + grpc_closure* ignored) {} // Constructor for channel_data. static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index dbe5b139f9..1127fff756 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -35,6 +35,7 @@ #include <string.h> +#include <grpc/slice.h> #include <grpc/status.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> @@ -47,46 +48,7 @@ #include "src/core/lib/iomgr/error_internal.h" #include "src/core/lib/profiling/timers.h" - -static void destroy_integer(void *key) {} - -static void *copy_integer(void *key) { return key; } - -static long compare_integers(void *key1, void *key2) { - return GPR_ICMP((uintptr_t)key1, (uintptr_t)key2); -} - -static void destroy_string(void *str) { gpr_free(str); } - -static void *copy_string(void *str) { return gpr_strdup(str); } - -static void destroy_err(void *err) { GRPC_ERROR_UNREF(err); } - -static void *copy_err(void *err) { return GRPC_ERROR_REF(err); } - -static void destroy_time(void *tm) { gpr_free(tm); } - -static gpr_timespec *box_time(gpr_timespec tm) { - gpr_timespec *out = gpr_malloc(sizeof(*out)); - *out = tm; - return out; -} - -static void *copy_time(void *tm) { return box_time(*(gpr_timespec *)tm); } - -static const gpr_avl_vtable avl_vtable_ints = {destroy_integer, copy_integer, - compare_integers, - destroy_integer, copy_integer}; - -static const gpr_avl_vtable avl_vtable_strs = {destroy_integer, copy_integer, - compare_integers, destroy_string, - copy_string}; - -static const gpr_avl_vtable avl_vtable_times = { - destroy_integer, copy_integer, compare_integers, destroy_time, copy_time}; - -static const gpr_avl_vtable avl_vtable_errs = { - destroy_integer, copy_integer, compare_integers, destroy_err, copy_err}; +#include "src/core/lib/slice/slice_internal.h" static const char *error_int_name(grpc_error_ints key) { switch (key) { @@ -120,6 +82,8 @@ static const char *error_int_name(grpc_error_ints key) { return "limit"; case GRPC_ERROR_INT_OCCURRED_DURING_WRITE: return "occurred_during_write"; + case GRPC_ERROR_INT_MAX: + GPR_UNREACHABLE_CODE(return "unknown"); } GPR_UNREACHABLE_CODE(return "unknown"); } @@ -150,6 +114,8 @@ static const char *error_str_name(grpc_error_strs key) { return "filename"; case GRPC_ERROR_STR_QUEUED_BUFFERS: return "queued_buffers"; + case GRPC_ERROR_STR_MAX: + GPR_UNREACHABLE_CODE(return "unknown"); } GPR_UNREACHABLE_CODE(return "unknown"); } @@ -158,6 +124,8 @@ static const char *error_time_name(grpc_error_times key) { switch (key) { case GRPC_ERROR_TIME_CREATED: return "created"; + case GRPC_ERROR_TIME_MAX: + GPR_UNREACHABLE_CODE(return "unknown"); } GPR_UNREACHABLE_CODE(return "unknown"); } @@ -172,25 +140,51 @@ grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line, const char *func) { if (grpc_error_is_special(err)) return err; gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, - err->refs.count, err->refs.count + 1, file, line, func); - gpr_ref(&err->refs); + gpr_atm_no_barrier_load(&err->atomics.refs.count), + gpr_atm_no_barrier_load(&err->atomics.refs.count) + 1, file, line, + func); + gpr_ref(&err->atomics.refs); return err; } #else grpc_error *grpc_error_ref(grpc_error *err) { if (grpc_error_is_special(err)) return err; - gpr_ref(&err->refs); + gpr_ref(&err->atomics.refs); return err; } #endif +static void unref_errs(grpc_error *err) { + uint8_t slot = err->first_err; + while (slot != UINT8_MAX) { + grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot); + GRPC_ERROR_UNREF(lerr->err); + GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX + : lerr->next != UINT8_MAX); + slot = lerr->next; + } +} + +static void unref_slice(grpc_slice slice) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_slice_unref_internal(&exec_ctx, slice); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void unref_strs(grpc_error *err) { + for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { + uint8_t slot = err->strs[which]; + if (slot != UINT8_MAX) { + unref_slice(*(grpc_slice *)(err->arena + slot)); + } + } +} + static void error_destroy(grpc_error *err) { GPR_ASSERT(!grpc_error_is_special(err)); - gpr_avl_unref(err->ints); - gpr_avl_unref(err->strs); - gpr_avl_unref(err->errs); - gpr_avl_unref(err->times); - gpr_free((void *)gpr_atm_acq_load(&err->error_string)); + unref_errs(err); + unref_strs(err); + gpr_free((void *)gpr_atm_acq_load(&err->atomics.error_string)); gpr_free(err); } @@ -199,81 +193,209 @@ void grpc_error_unref(grpc_error *err, const char *file, int line, const char *func) { if (grpc_error_is_special(err)) return; gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, - err->refs.count, err->refs.count - 1, file, line, func); - if (gpr_unref(&err->refs)) { + gpr_atm_no_barrier_load(&err->atomics.refs.count), + gpr_atm_no_barrier_load(&err->atomics.refs.count) - 1, file, line, + func); + if (gpr_unref(&err->atomics.refs)) { error_destroy(err); } } #else void grpc_error_unref(grpc_error *err) { if (grpc_error_is_special(err)) return; - if (gpr_unref(&err->refs)) { + if (gpr_unref(&err->atomics.refs)) { error_destroy(err); } } #endif +static uint8_t get_placement(grpc_error **err, size_t size) { + GPR_ASSERT(*err); + uint8_t slots = (uint8_t)(size / sizeof(intptr_t)); + if ((*err)->arena_size + slots > (*err)->arena_capacity) { + (*err)->arena_capacity = (uint8_t)(3 * (*err)->arena_capacity / 2); + *err = gpr_realloc( + *err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t)); + } + uint8_t placement = (*err)->arena_size; + (*err)->arena_size = (uint8_t)((*err)->arena_size + slots); + return placement; +} + +static void internal_set_int(grpc_error **err, grpc_error_ints which, + intptr_t value) { + // GPR_ASSERT((*err)->ints[which] == UINT8_MAX); // TODO, enforce this + uint8_t slot = (*err)->ints[which]; + if (slot == UINT8_MAX) { + slot = get_placement(err, sizeof(value)); + } + (*err)->ints[which] = slot; + (*err)->arena[slot] = value; +} + +static void internal_set_str(grpc_error **err, grpc_error_strs which, + grpc_slice value) { + // GPR_ASSERT((*err)->strs[which] == UINT8_MAX); // TODO, enforce this + uint8_t slot = (*err)->strs[which]; + if (slot == UINT8_MAX) { + slot = get_placement(err, sizeof(value)); + } else { + unref_slice(*(grpc_slice *)((*err)->arena + slot)); + } + (*err)->strs[which] = slot; + memcpy((*err)->arena + slot, &value, sizeof(value)); +} + +static void internal_set_time(grpc_error **err, grpc_error_times which, + gpr_timespec value) { + // GPR_ASSERT((*err)->times[which] == UINT8_MAX); // TODO, enforce this + uint8_t slot = (*err)->times[which]; + if (slot == UINT8_MAX) { + slot = get_placement(err, sizeof(value)); + } + (*err)->times[which] = slot; + memcpy((*err)->arena + slot, &value, sizeof(value)); +} + +static void internal_add_error(grpc_error **err, grpc_error *new) { + grpc_linked_error new_last = {new, UINT8_MAX}; + uint8_t slot = get_placement(err, sizeof(grpc_linked_error)); + if ((*err)->first_err == UINT8_MAX) { + GPR_ASSERT((*err)->last_err == UINT8_MAX); + (*err)->last_err = slot; + (*err)->first_err = slot; + } else { + GPR_ASSERT((*err)->last_err != UINT8_MAX); + grpc_linked_error *old_last = + (grpc_linked_error *)((*err)->arena + (*err)->last_err); + old_last->next = slot; + (*err)->last_err = slot; + } + memcpy((*err)->arena + slot, &new_last, sizeof(grpc_linked_error)); +} + +#define SLOTS_PER_INT (sizeof(intptr_t) / sizeof(intptr_t)) +#define SLOTS_PER_STR (sizeof(grpc_slice) / sizeof(intptr_t)) +#define SLOTS_PER_TIME (sizeof(gpr_timespec) / sizeof(intptr_t)) +#define SLOTS_PER_LINKED_ERROR (sizeof(grpc_linked_error) / sizeof(intptr_t)) + +// size of storing one int and two slices and a timespec. For line, desc, file, +// and time created +#define DEFAULT_ERROR_CAPACITY \ + (SLOTS_PER_INT + (SLOTS_PER_STR * 2) + SLOTS_PER_TIME) + +// It is very common to include and extra int and string in an error +#define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME) + grpc_error *grpc_error_create(const char *file, int line, const char *desc, grpc_error **referencing, size_t num_referencing) { GPR_TIMER_BEGIN("grpc_error_create", 0); - grpc_error *err = gpr_malloc(sizeof(*err)); + uint8_t initial_arena_capacity = (uint8_t)( + DEFAULT_ERROR_CAPACITY + + (uint8_t)(num_referencing * SLOTS_PER_LINKED_ERROR) + SURPLUS_CAPACITY); + grpc_error *err = + gpr_malloc(sizeof(*err) + initial_arena_capacity * sizeof(intptr_t)); if (err == NULL) { // TODO(ctiller): make gpr_malloc return NULL return GRPC_ERROR_OOM; } #ifdef GRPC_ERROR_REFCOUNT_DEBUG gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line); #endif - err->ints = gpr_avl_add(gpr_avl_create(&avl_vtable_ints), - (void *)(uintptr_t)GRPC_ERROR_INT_FILE_LINE, - (void *)(uintptr_t)line); - err->strs = gpr_avl_add( - gpr_avl_add(gpr_avl_create(&avl_vtable_strs), - (void *)(uintptr_t)GRPC_ERROR_STR_FILE, gpr_strdup(file)), - (void *)(uintptr_t)GRPC_ERROR_STR_DESCRIPTION, gpr_strdup(desc)); - err->errs = gpr_avl_create(&avl_vtable_errs); - err->next_err = 0; - for (size_t i = 0; i < num_referencing; i++) { + + err->arena_size = 0; + err->arena_capacity = initial_arena_capacity; + err->first_err = UINT8_MAX; + err->last_err = UINT8_MAX; + + memset(err->ints, UINT8_MAX, GRPC_ERROR_INT_MAX); + memset(err->strs, UINT8_MAX, GRPC_ERROR_STR_MAX); + memset(err->times, UINT8_MAX, GRPC_ERROR_TIME_MAX); + + internal_set_int(&err, GRPC_ERROR_INT_FILE_LINE, line); + internal_set_str(&err, GRPC_ERROR_STR_FILE, + grpc_slice_from_static_string(file)); + internal_set_str( + &err, GRPC_ERROR_STR_DESCRIPTION, + grpc_slice_from_copied_buffer( + desc, + strlen(desc) + + 1)); // TODO, pull this up. // TODO(ncteisen), pull this up. + + for (size_t i = 0; i < num_referencing; ++i) { if (referencing[i] == GRPC_ERROR_NONE) continue; - err->errs = gpr_avl_add(err->errs, (void *)(err->next_err++), - GRPC_ERROR_REF(referencing[i])); - } - err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times), - (void *)(uintptr_t)GRPC_ERROR_TIME_CREATED, - box_time(gpr_now(GPR_CLOCK_REALTIME))); - gpr_atm_no_barrier_store(&err->error_string, 0); - gpr_ref_init(&err->refs, 1); + internal_add_error( + &err, + GRPC_ERROR_REF( + referencing[i])); // TODO(ncteisen), change ownership semantics + } + + internal_set_time(&err, GRPC_ERROR_TIME_CREATED, gpr_now(GPR_CLOCK_REALTIME)); + + gpr_atm_no_barrier_store(&err->atomics.error_string, 0); + gpr_ref_init(&err->atomics.refs, 1); GPR_TIMER_END("grpc_error_create", 0); return err; } +static void ref_strs(grpc_error *err) { + for (size_t i = 0; i < GRPC_ERROR_STR_MAX; ++i) { + uint8_t slot = err->strs[i]; + if (slot != UINT8_MAX) { + grpc_slice_ref_internal(*(grpc_slice *)(err->arena + slot)); + } + } +} + +static void ref_errs(grpc_error *err) { + uint8_t slot = err->first_err; + while (slot != UINT8_MAX) { + grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot); + GRPC_ERROR_REF(lerr->err); + slot = lerr->next; + } +} + static grpc_error *copy_error_and_unref(grpc_error *in) { GPR_TIMER_BEGIN("copy_error_and_unref", 0); grpc_error *out; if (grpc_error_is_special(in)) { - if (in == GRPC_ERROR_NONE) - out = grpc_error_set_int(GRPC_ERROR_CREATE("no error"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK); - else if (in == GRPC_ERROR_OOM) - out = GRPC_ERROR_CREATE("oom"); - else if (in == GRPC_ERROR_CANCELLED) - out = - grpc_error_set_int(GRPC_ERROR_CREATE("cancelled"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED); - else - out = GRPC_ERROR_CREATE("unknown"); + out = GRPC_ERROR_CREATE("unknown"); + if (in == GRPC_ERROR_NONE) { + internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, + grpc_slice_from_static_string("no error")); + internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK); + } else if (in == GRPC_ERROR_OOM) { + internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, + grpc_slice_from_static_string("oom")); + } else if (in == GRPC_ERROR_CANCELLED) { + internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, + grpc_slice_from_static_string("cancelled")); + internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED); + } + } else if (gpr_ref_is_unique(&in->atomics.refs)) { + out = in; } else { - out = gpr_malloc(sizeof(*out)); + uint8_t new_arena_capacity = in->arena_capacity; + // the returned err will be added to, so we ensure this is room to avoid + // unneeded allocations. + if (in->arena_capacity - in->arena_size < (uint8_t)SLOTS_PER_STR) { + new_arena_capacity = (uint8_t)(3 * new_arena_capacity / 2); + } + out = gpr_malloc(sizeof(*in) + new_arena_capacity * sizeof(intptr_t)); #ifdef GRPC_ERROR_REFCOUNT_DEBUG gpr_log(GPR_DEBUG, "%p create copying %p", out, in); #endif - out->ints = gpr_avl_ref(in->ints); - out->strs = gpr_avl_ref(in->strs); - out->errs = gpr_avl_ref(in->errs); - out->times = gpr_avl_ref(in->times); - gpr_atm_no_barrier_store(&out->error_string, 0); - out->next_err = in->next_err; - gpr_ref_init(&out->refs, 1); + // bulk memcpy of the rest of the struct. + size_t skip = sizeof(&out->atomics); + memcpy((void *)((uintptr_t)out + skip), (void *)((uintptr_t)in + skip), + sizeof(*in) + (in->arena_size * sizeof(intptr_t)) - skip); + // manually set the atomics and the new capacity + gpr_atm_no_barrier_store(&out->atomics.error_string, 0); + gpr_ref_init(&out->atomics.refs, 1); + out->arena_capacity = new_arena_capacity; + ref_strs(out); + ref_errs(out); GRPC_ERROR_UNREF(in); } GPR_TIMER_END("copy_error_and_unref", 0); @@ -284,7 +406,7 @@ grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which, intptr_t value) { GPR_TIMER_BEGIN("grpc_error_set_int", 0); grpc_error *new = copy_error_and_unref(src); - new->ints = gpr_avl_add(new->ints, (void *)(uintptr_t)which, (void *)value); + internal_set_int(&new, which, value); GPR_TIMER_END("grpc_error_set_int", 0); return new; } @@ -302,7 +424,6 @@ static special_error_status_map error_status_map[] = { bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) { GPR_TIMER_BEGIN("grpc_error_get_int", 0); - void *pp; if (grpc_error_is_special(err)) { if (which == GRPC_ERROR_INT_GRPC_STATUS) { for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) { @@ -316,8 +437,9 @@ bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) { GPR_TIMER_END("grpc_error_get_int", 0); return false; } - if (gpr_avl_maybe_get(err->ints, (void *)(uintptr_t)which, &pp)) { - if (p != NULL) *p = (intptr_t)pp; + uint8_t slot = err->ints[which]; + if (slot != UINT8_MAX) { + if (p != NULL) *p = err->arena[slot]; GPR_TIMER_END("grpc_error_get_int", 0); return true; } @@ -329,8 +451,9 @@ grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which, const char *value) { GPR_TIMER_BEGIN("grpc_error_set_str", 0); grpc_error *new = copy_error_and_unref(src); - new->strs = - gpr_avl_add(new->strs, (void *)(uintptr_t)which, gpr_strdup(value)); + internal_set_str(&new, which, + grpc_slice_from_copied_buffer( + value, strlen(value) + 1)); // TODO, pull this up. GPR_TIMER_END("grpc_error_set_str", 0); return new; } @@ -346,13 +469,19 @@ const char *grpc_error_get_str(grpc_error *err, grpc_error_strs which) { } return NULL; } - return gpr_avl_get(err->strs, (void *)(uintptr_t)which); + uint8_t slot = err->strs[which]; + if (slot != UINT8_MAX) { + return (const char *)GRPC_SLICE_START_PTR( + *(grpc_slice *)(err->arena + slot)); + } else { + return NULL; + } } grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) { GPR_TIMER_BEGIN("grpc_error_add_child", 0); grpc_error *new = copy_error_and_unref(src); - new->errs = gpr_avl_add(new->errs, (void *)(new->next_err++), child); + internal_add_error(&new, child); GPR_TIMER_END("grpc_error_add_child", 0); return new; } @@ -372,42 +501,6 @@ typedef struct { size_t cap_kvs; } kv_pairs; -static void append_kv(kv_pairs *kvs, char *key, char *value) { - if (kvs->num_kvs == kvs->cap_kvs) { - kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4); - kvs->kvs = gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs); - } - kvs->kvs[kvs->num_kvs].key = key; - kvs->kvs[kvs->num_kvs].value = value; - kvs->num_kvs++; -} - -static void collect_kvs(gpr_avl_node *node, char *key(void *k), - char *fmt(void *v), kv_pairs *kvs) { - if (node == NULL) return; - append_kv(kvs, key(node->key), fmt(node->value)); - collect_kvs(node->left, key, fmt, kvs); - collect_kvs(node->right, key, fmt, kvs); -} - -static char *key_int(void *p) { - return gpr_strdup(error_int_name((grpc_error_ints)(uintptr_t)p)); -} - -static char *key_str(void *p) { - return gpr_strdup(error_str_name((grpc_error_strs)(uintptr_t)p)); -} - -static char *key_time(void *p) { - return gpr_strdup(error_time_name((grpc_error_times)(uintptr_t)p)); -} - -static char *fmt_int(void *p) { - char *s; - gpr_asprintf(&s, "%" PRIdPTR, (intptr_t)p); - return s; -} - static void append_chr(char c, char **s, size_t *sz, size_t *cap) { if (*sz == *cap) { *cap = GPR_MAX(8, 3 * *cap / 2); @@ -459,6 +552,40 @@ static void append_esc_str(const char *str, char **s, size_t *sz, size_t *cap) { append_chr('"', s, sz, cap); } +static void append_kv(kv_pairs *kvs, char *key, char *value) { + if (kvs->num_kvs == kvs->cap_kvs) { + kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4); + kvs->kvs = gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs); + } + kvs->kvs[kvs->num_kvs].key = key; + kvs->kvs[kvs->num_kvs].value = value; + kvs->num_kvs++; +} + +static char *key_int(grpc_error_ints which) { + return gpr_strdup(error_int_name(which)); +} + +static char *fmt_int(intptr_t p) { + char *s; + gpr_asprintf(&s, "%" PRIdPTR, p); + return s; +} + +static void collect_ints_kvs(grpc_error *err, kv_pairs *kvs) { + for (size_t which = 0; which < GRPC_ERROR_INT_MAX; ++which) { + uint8_t slot = err->ints[which]; + if (slot != UINT8_MAX) { + append_kv(kvs, key_int((grpc_error_ints)which), + fmt_int(err->arena[slot])); + } + } +} + +static char *key_str(grpc_error_strs which) { + return gpr_strdup(error_str_name(which)); +} + static char *fmt_str(void *p) { char *s = NULL; size_t sz = 0; @@ -468,8 +595,22 @@ static char *fmt_str(void *p) { return s; } -static char *fmt_time(void *p) { - gpr_timespec tm = *(gpr_timespec *)p; +static void collect_strs_kvs(grpc_error *err, kv_pairs *kvs) { + for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { + uint8_t slot = err->strs[which]; + if (slot != UINT8_MAX) { + append_kv( + kvs, key_str((grpc_error_strs)which), + fmt_str(GRPC_SLICE_START_PTR(*(grpc_slice *)(err->arena + slot)))); + } + } +} + +static char *key_time(grpc_error_times which) { + return gpr_strdup(error_time_name(which)); +} + +static char *fmt_time(gpr_timespec tm) { char *out; char *pfx = "!!"; switch (tm.clock_type) { @@ -490,24 +631,37 @@ static char *fmt_time(void *p) { return out; } -static void add_errs(gpr_avl_node *n, char **s, size_t *sz, size_t *cap, - bool *first) { - if (n == NULL) return; - add_errs(n->left, s, sz, cap, first); - if (!*first) append_chr(',', s, sz, cap); - *first = false; - const char *e = grpc_error_string(n->value); - append_str(e, s, sz, cap); - add_errs(n->right, s, sz, cap, first); +static void collect_times_kvs(grpc_error *err, kv_pairs *kvs) { + for (size_t which = 0; which < GRPC_ERROR_TIME_MAX; ++which) { + uint8_t slot = err->times[which]; + if (slot != UINT8_MAX) { + append_kv(kvs, key_time((grpc_error_times)which), + fmt_time(*(gpr_timespec *)(err->arena + slot))); + } + } +} + +static void add_errs(grpc_error *err, char **s, size_t *sz, size_t *cap) { + uint8_t slot = err->first_err; + bool first = true; + while (slot != UINT8_MAX) { + grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot); + if (!first) append_chr(',', s, sz, cap); + first = false; + const char *e = grpc_error_string(lerr->err); + append_str(e, s, sz, cap); + GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX + : lerr->next != UINT8_MAX); + slot = lerr->next; + } } static char *errs_string(grpc_error *err) { char *s = NULL; size_t sz = 0; size_t cap = 0; - bool first = true; append_chr('[', &s, &sz, &cap); - add_errs(err->errs.root, &s, &sz, &cap, &first); + add_errs(err, &s, &sz, &cap); append_chr(']', &s, &sz, &cap); append_chr(0, &s, &sz, &cap); return s; @@ -546,7 +700,7 @@ const char *grpc_error_string(grpc_error *err) { if (err == GRPC_ERROR_OOM) return oom_error_string; if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string; - void *p = (void *)gpr_atm_acq_load(&err->error_string); + void *p = (void *)gpr_atm_acq_load(&err->atomics.error_string); if (p != NULL) { GPR_TIMER_END("grpc_error_string", 0); return p; @@ -555,10 +709,10 @@ const char *grpc_error_string(grpc_error *err) { kv_pairs kvs; memset(&kvs, 0, sizeof(kvs)); - collect_kvs(err->ints.root, key_int, fmt_int, &kvs); - collect_kvs(err->strs.root, key_str, fmt_str, &kvs); - collect_kvs(err->times.root, key_time, fmt_time, &kvs); - if (!gpr_avl_is_empty(err->errs)) { + collect_ints_kvs(err, &kvs); + collect_strs_kvs(err, &kvs); + collect_times_kvs(err, &kvs); + if (err->first_err != UINT8_MAX) { append_kv(&kvs, gpr_strdup("referenced_errors"), errs_string(err)); } @@ -566,9 +720,9 @@ const char *grpc_error_string(grpc_error *err) { char *out = finish_kvs(&kvs); - if (!gpr_atm_rel_cas(&err->error_string, 0, (gpr_atm)out)) { + if (!gpr_atm_rel_cas(&err->atomics.error_string, 0, (gpr_atm)out)) { gpr_free(out); - out = (char *)gpr_atm_no_barrier_load(&err->error_string); + out = (char *)gpr_atm_no_barrier_load(&err->atomics.error_string); } GPR_TIMER_END("grpc_error_string", 0); diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index 2613512acb..eb953947ae 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -102,6 +102,9 @@ typedef enum { GRPC_ERROR_INT_LIMIT, /// chttp2: did the error occur while a write was in progress GRPC_ERROR_INT_OCCURRED_DURING_WRITE, + + /// Must always be last + GRPC_ERROR_INT_MAX, } grpc_error_ints; typedef enum { @@ -129,11 +132,17 @@ typedef enum { GRPC_ERROR_STR_KEY, /// value associated with the error GRPC_ERROR_STR_VALUE, + + /// Must always be last + GRPC_ERROR_STR_MAX, } grpc_error_strs; typedef enum { /// timestamp of error creation GRPC_ERROR_TIME_CREATED, + + /// Must always be last + GRPC_ERROR_TIME_MAX, } grpc_error_times; /// The following "special" errors can be propagated without allocating memory. @@ -184,8 +193,6 @@ void grpc_error_unref(grpc_error *err); grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which, intptr_t value) GRPC_MUST_USE_RESULT; bool grpc_error_get_int(grpc_error *error, grpc_error_ints which, intptr_t *p); -grpc_error *grpc_error_set_time(grpc_error *src, grpc_error_times which, - gpr_timespec value) GRPC_MUST_USE_RESULT; grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which, const char *value) GRPC_MUST_USE_RESULT; /// Returns NULL if the specified string is not set. diff --git a/src/core/lib/iomgr/error_internal.h b/src/core/lib/iomgr/error_internal.h index 1c89ead4ed..7f204df1b2 100644 --- a/src/core/lib/iomgr/error_internal.h +++ b/src/core/lib/iomgr/error_internal.h @@ -35,18 +35,39 @@ #define GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H #include <inttypes.h> -#include <stdbool.h> +#include <stdbool.h> // TODO, do we need this? -#include <grpc/support/avl.h> +#include <grpc/support/sync.h> +typedef struct grpc_linked_error grpc_linked_error; + +struct grpc_linked_error { + grpc_error *err; + uint8_t next; +}; + +// c core representation of an error. See error.h for high level description of +// this object. struct grpc_error { - gpr_refcount refs; - gpr_avl ints; - gpr_avl strs; - gpr_avl times; - gpr_avl errs; - uintptr_t next_err; - gpr_atm error_string; + // All atomics in grpc_error must be stored in this nested struct. The rest of + // the object is memcpy-ed in bulk in copy_and_unref. + struct atomics { + gpr_refcount refs; + gpr_atm error_string; + } atomics; + // These arrays index into dynamic arena at the bottom of the struct. + // UINT8_MAX is used as a sentinel value. + uint8_t ints[GRPC_ERROR_INT_MAX]; + uint8_t strs[GRPC_ERROR_STR_MAX]; + uint8_t times[GRPC_ERROR_TIME_MAX]; + // The child errors are stored in the arena, but are effectively a linked list + // structure, since they are contained withing grpc_linked_error objects. + uint8_t first_err; + uint8_t last_err; + // The arena is dynamically reallocated with a grow factor of 1.5. + uint8_t arena_size; + uint8_t arena_capacity; + intptr_t arena[0]; }; bool grpc_error_is_special(grpc_error *err); diff --git a/src/core/lib/iomgr/pollset_uv.c b/src/core/lib/iomgr/pollset_uv.c index af33949c69..a2f81bcd78 100644 --- a/src/core/lib/iomgr/pollset_uv.c +++ b/src/core/lib/iomgr/pollset_uv.c @@ -39,6 +39,7 @@ #include <string.h> +#include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/sync.h> @@ -61,25 +62,30 @@ gpr_mu grpc_polling_mu; immediately in the next loop iteration. Note: In the future, if there is a bug that involves missing wakeups in the future, try adding a uv_async_t to kick the loop differently */ -uv_timer_t dummy_uv_handle; +uv_timer_t *dummy_uv_handle; size_t grpc_pollset_size() { return sizeof(grpc_pollset); } void dummy_timer_cb(uv_timer_t *handle) {} +void dummy_handle_close_cb(uv_handle_t *handle) { gpr_free(handle); } + void grpc_pollset_global_init(void) { gpr_mu_init(&grpc_polling_mu); - uv_timer_init(uv_default_loop(), &dummy_uv_handle); + dummy_uv_handle = gpr_malloc(sizeof(uv_timer_t)); + uv_timer_init(uv_default_loop(), dummy_uv_handle); grpc_pollset_work_run_loop = 1; } -static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; } - void grpc_pollset_global_shutdown(void) { gpr_mu_destroy(&grpc_polling_mu); - uv_close((uv_handle_t *)&dummy_uv_handle, timer_close_cb); + uv_close((uv_handle_t *)dummy_uv_handle, dummy_handle_close_cb); } +static void timer_run_cb(uv_timer_t *timer) {} + +static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; } + void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) { *mu = &grpc_polling_mu; uv_timer_init(uv_default_loop(), &pollset->timer); @@ -95,7 +101,7 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, uv_run(uv_default_loop(), UV_RUN_NOWAIT); } else { // kick the loop once - uv_timer_start(&dummy_uv_handle, dummy_timer_cb, 0, 0); + uv_timer_start(dummy_uv_handle, dummy_timer_cb, 0, 0); } grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE); } @@ -111,8 +117,6 @@ void grpc_pollset_destroy(grpc_pollset *pollset) { } } -static void timer_run_cb(uv_timer_t *timer) {} - grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, gpr_timespec now, gpr_timespec deadline) { @@ -145,7 +149,7 @@ grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_error *grpc_pollset_kick(grpc_pollset *pollset, grpc_pollset_worker *specific_worker) { - uv_timer_start(&dummy_uv_handle, dummy_timer_cb, 0, 0); + uv_timer_start(dummy_uv_handle, dummy_timer_cb, 0, 0); return GRPC_ERROR_NONE; } diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index f1897bb91f..94a454c0b7 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -39,6 +39,7 @@ #if defined(GRPC_UV) // Do nothing #elif defined(GPR_MANYLINUX1) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 @@ -65,6 +66,7 @@ #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_LINUX) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 @@ -90,6 +92,7 @@ #define GRPC_POSIX_SOCKETUTILS #endif #elif defined(GPR_APPLE) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_SO_NOSIGPIPE 1 #define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_MSG_IOVLEN_TYPE int @@ -100,6 +103,7 @@ #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_FREEBSD) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_SO_NOSIGPIPE 1 #define GRPC_HAVE_UNIX_SOCKET 1 diff --git a/src/core/lib/iomgr/resolve_address_uv.c b/src/core/lib/iomgr/resolve_address_uv.c index 79ff910738..4d715be94c 100644 --- a/src/core/lib/iomgr/resolve_address_uv.c +++ b/src/core/lib/iomgr/resolve_address_uv.c @@ -40,6 +40,7 @@ #include <grpc/support/host_port.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> +#include <grpc/support/useful.h> #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" @@ -54,8 +55,36 @@ typedef struct request { grpc_closure *on_done; grpc_resolved_addresses **addresses; struct addrinfo *hints; + char *host; + char *port; } request; +static int retry_named_port_failure(int status, request *r, + uv_getaddrinfo_cb getaddrinfo_cb) { + if (status != 0) { + // This loop is copied from resolve_address_posix.c + char *svc[][2] = {{"http", "80"}, {"https", "443"}}; + for (size_t i = 0; i < GPR_ARRAY_SIZE(svc); i++) { + if (strcmp(r->port, svc[i][0]) == 0) { + int retry_status; + uv_getaddrinfo_t *req = gpr_malloc(sizeof(uv_getaddrinfo_t)); + req->data = r; + retry_status = uv_getaddrinfo(uv_default_loop(), req, getaddrinfo_cb, + r->host, svc[i][1], r->hints); + if (retry_status < 0 || getaddrinfo_cb == NULL) { + // The callback will not be called + gpr_free(req); + } + return retry_status; + } + } + } + /* If this function calls uv_getaddrinfo, it will return that function's + return value. That function only returns numbers <=0, so we can safely + return 1 to indicate that we never retried */ + return 1; +} + static grpc_error *handle_addrinfo_result(int status, struct addrinfo *result, grpc_resolved_addresses **addresses) { struct addrinfo *resp; @@ -97,13 +126,21 @@ static void getaddrinfo_callback(uv_getaddrinfo_t *req, int status, request *r = (request *)req->data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_error *error; + int retry_status; + + gpr_free(req); + retry_status = retry_named_port_failure(status, r, getaddrinfo_callback); + if (retry_status == 0) { + // The request is being retried. Nothing should be done here + return; + } + /* Either no retry was attempted, or the retry failed. Either way, the + original error probably has more interesting information */ error = handle_addrinfo_result(status, res, r->addresses); grpc_closure_sched(&exec_ctx, r->on_done, error); grpc_exec_ctx_finish(&exec_ctx); - gpr_free(r->hints); gpr_free(r); - gpr_free(req); uv_freeaddrinfo(res); } @@ -143,6 +180,7 @@ static grpc_error *blocking_resolve_address_impl( uv_getaddrinfo_t req; int s; grpc_error *err; + int retry_status; req.addrinfo = NULL; @@ -158,6 +196,12 @@ static grpc_error *blocking_resolve_address_impl( hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ s = uv_getaddrinfo(uv_default_loop(), &req, NULL, host, port, &hints); + request r = { + .addresses = addresses, .hints = &hints, .host = host, .port = port}; + retry_status = retry_named_port_failure(s, &r, NULL); + if (retry_status <= 0) { + s = retry_status; + } err = handle_addrinfo_result(s, req.addrinfo, addresses); done: @@ -200,6 +244,8 @@ static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name, r = gpr_malloc(sizeof(request)); r->on_done = on_done; r->addresses = addrs; + r->host = host; + r->port = port; req = gpr_malloc(sizeof(uv_getaddrinfo_t)); req->data = r; @@ -222,6 +268,8 @@ static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name, gpr_free(r); gpr_free(req); gpr_free(hints); + gpr_free(host); + gpr_free(port); } } diff --git a/src/core/lib/iomgr/tcp_client_uv.c b/src/core/lib/iomgr/tcp_client_uv.c index ae66577caf..618483d9cb 100644 --- a/src/core/lib/iomgr/tcp_client_uv.c +++ b/src/core/lib/iomgr/tcp_client_uv.c @@ -76,7 +76,6 @@ static void uv_tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", connect->addr_name, str); - grpc_error_free_string(str); } if (error == GRPC_ERROR_NONE) { /* error == NONE implies that the timer ran out, and wasn't cancelled. If diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 5f286a6723..e242631fc0 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -44,11 +44,8 @@ #include <errno.h> #include <fcntl.h> -#include <ifaddrs.h> -#include <limits.h> #include <netinet/in.h> #include <netinet/tcp.h> -#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/stat.h> @@ -67,82 +64,10 @@ #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" -#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 - -static gpr_once s_init_max_accept_queue_size; -static int s_max_accept_queue_size; - -/* one listening port */ -typedef struct grpc_tcp_listener grpc_tcp_listener; -struct grpc_tcp_listener { - int fd; - grpc_fd *emfd; - grpc_tcp_server *server; - grpc_resolved_address addr; - int port; - unsigned port_index; - unsigned fd_index; - grpc_closure read_closure; - grpc_closure destroyed_closure; - struct grpc_tcp_listener *next; - /* sibling is a linked list of all listeners for a given port. add_port and - clone_port place all new listeners in the same sibling list. A member of - the 'sibling' list is also a member of the 'next' list. The head of each - sibling list has is_sibling==0, and subsequent members of sibling lists - have is_sibling==1. is_sibling allows separate sibling lists to be - identified while iterating through 'next'. */ - struct grpc_tcp_listener *sibling; - int is_sibling; -}; - -/* the overall server */ -struct grpc_tcp_server { - gpr_refcount refs; - /* Called whenever accept() succeeds on a server port. */ - grpc_tcp_server_cb on_accept_cb; - void *on_accept_cb_arg; - - gpr_mu mu; - - /* active port count: how many ports are actually still listening */ - size_t active_ports; - /* destroyed port count: how many ports are completely destroyed */ - size_t destroyed_ports; - - /* is this server shutting down? */ - bool shutdown; - /* have listeners been shutdown? */ - bool shutdown_listeners; - /* use SO_REUSEPORT */ - bool so_reuseport; - /* expand wildcard addresses to a list of all local addresses */ - bool expand_wildcard_addrs; - - /* linked list of server ports */ - grpc_tcp_listener *head; - grpc_tcp_listener *tail; - unsigned nports; - - /* List of closures passed to shutdown_starting_add(). */ - grpc_closure_list shutdown_starting; - - /* shutdown callback */ - grpc_closure *shutdown_complete; - - /* all pollsets interested in new connections */ - grpc_pollset **pollsets; - /* number of pollsets in the pollsets array */ - size_t pollset_count; - - /* next pollset to assign a channel to */ - gpr_atm next_pollset_to_assign; - - grpc_resource_quota *resource_quota; -}; - static gpr_once check_init = GPR_ONCE_INIT; static bool has_so_reuseport = false; @@ -301,99 +226,6 @@ static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { } } -/* get max listen queue size on linux */ -static void init_max_accept_queue_size(void) { - int n = SOMAXCONN; - char buf[64]; - FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r"); - if (fp == NULL) { - /* 2.4 kernel. */ - s_max_accept_queue_size = SOMAXCONN; - return; - } - if (fgets(buf, sizeof buf, fp)) { - char *end; - long i = strtol(buf, &end, 10); - if (i > 0 && i <= INT_MAX && end && *end == 0) { - n = (int)i; - } - } - fclose(fp); - s_max_accept_queue_size = n; - - if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) { - gpr_log(GPR_INFO, - "Suspiciously small accept queue (%d) will probably lead to " - "connection drops", - s_max_accept_queue_size); - } -} - -static int get_max_accept_queue_size(void) { - gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size); - return s_max_accept_queue_size; -} - -/* Prepare a recently-created socket for listening. */ -static grpc_error *prepare_socket(int fd, const grpc_resolved_address *addr, - bool so_reuseport, int *port) { - grpc_resolved_address sockname_temp; - grpc_error *err = GRPC_ERROR_NONE; - - GPR_ASSERT(fd >= 0); - - if (so_reuseport && !grpc_is_unix_socket(addr)) { - err = grpc_set_socket_reuse_port(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - } - - err = grpc_set_socket_nonblocking(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_cloexec(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - if (!grpc_is_unix_socket(addr)) { - err = grpc_set_socket_low_latency(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_reuse_addr(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - } - err = grpc_set_socket_no_sigpipe_if_possible(fd); - if (err != GRPC_ERROR_NONE) goto error; - - GPR_ASSERT(addr->len < ~(socklen_t)0); - if (bind(fd, (struct sockaddr *)addr->addr, (socklen_t)addr->len) < 0) { - err = GRPC_OS_ERROR(errno, "bind"); - goto error; - } - - if (listen(fd, get_max_accept_queue_size()) < 0) { - err = GRPC_OS_ERROR(errno, "listen"); - goto error; - } - - sockname_temp.len = sizeof(struct sockaddr_storage); - - if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, - (socklen_t *)&sockname_temp.len) < 0) { - err = GRPC_OS_ERROR(errno, "getsockname"); - goto error; - } - - *port = grpc_sockaddr_get_port(&sockname_temp); - return GRPC_ERROR_NONE; - -error: - GPR_ASSERT(err != GRPC_ERROR_NONE); - if (fd >= 0) { - close(fd); - } - grpc_error *ret = grpc_error_set_int( - GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1), - GRPC_ERROR_INT_FD, fd); - GRPC_ERROR_UNREF(err); - return ret; -} - /* event manager callback when reads are ready */ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { grpc_tcp_listener *sp = arg; @@ -477,216 +309,6 @@ error: } } -static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd, - const grpc_resolved_address *addr, - unsigned port_index, unsigned fd_index, - grpc_tcp_listener **listener) { - grpc_tcp_listener *sp = NULL; - int port = -1; - char *addr_str; - char *name; - - grpc_error *err = prepare_socket(fd, addr, s->so_reuseport, &port); - if (err == GRPC_ERROR_NONE) { - GPR_ASSERT(port > 0); - grpc_sockaddr_to_string(&addr_str, addr, 1); - gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); - gpr_mu_lock(&s->mu); - s->nports++; - GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); - sp = gpr_malloc(sizeof(grpc_tcp_listener)); - sp->next = NULL; - if (s->head == NULL) { - s->head = sp; - } else { - s->tail->next = sp; - } - s->tail = sp; - sp->server = s; - sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name); - memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); - sp->port = port; - sp->port_index = port_index; - sp->fd_index = fd_index; - sp->is_sibling = 0; - sp->sibling = NULL; - GPR_ASSERT(sp->emfd); - gpr_mu_unlock(&s->mu); - gpr_free(addr_str); - gpr_free(name); - } - - *listener = sp; - return err; -} - -/* If successful, add a listener to s for addr, set *dsmode for the socket, and - return the *listener. */ -static grpc_error *add_addr_to_server(grpc_tcp_server *s, - const grpc_resolved_address *addr, - unsigned port_index, unsigned fd_index, - grpc_dualstack_mode *dsmode, - grpc_tcp_listener **listener) { - grpc_resolved_address addr4_copy; - int fd; - grpc_error *err = - grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd); - if (err != GRPC_ERROR_NONE) { - return err; - } - if (*dsmode == GRPC_DSMODE_IPV4 && - grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { - addr = &addr4_copy; - } - return add_socket_to_server(s, fd, addr, port_index, fd_index, listener); -} - -/* Bind to "::" to get a port number not used by any address. */ -static grpc_error *get_unused_port(int *port) { - grpc_resolved_address wild; - grpc_sockaddr_make_wildcard6(0, &wild); - grpc_dualstack_mode dsmode; - int fd; - grpc_error *err = - grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd); - if (err != GRPC_ERROR_NONE) { - return err; - } - if (dsmode == GRPC_DSMODE_IPV4) { - grpc_sockaddr_make_wildcard4(0, &wild); - } - if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) { - err = GRPC_OS_ERROR(errno, "bind"); - close(fd); - return err; - } - if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) != - 0) { - err = GRPC_OS_ERROR(errno, "getsockname"); - close(fd); - return err; - } - close(fd); - *port = grpc_sockaddr_get_port(&wild); - return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE; -} - -/* Return the listener in s with address addr or NULL. */ -static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s, - grpc_resolved_address *addr) { - grpc_tcp_listener *l; - gpr_mu_lock(&s->mu); - for (l = s->head; l != NULL; l = l->next) { - if (l->addr.len != addr->len) { - continue; - } - if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) { - break; - } - } - gpr_mu_unlock(&s->mu); - return l; -} - -/* Get all addresses assigned to network interfaces on the machine and create a - listener for each. requested_port is the port to use for every listener, or 0 - to select one random port that will be used for every listener. Set *out_port - to the port selected. Return GRPC_ERROR_NONE only if all listeners were - added. */ -static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s, - unsigned port_index, - int requested_port, - int *out_port) { - struct ifaddrs *ifa = NULL; - struct ifaddrs *ifa_it; - unsigned fd_index = 0; - grpc_tcp_listener *sp = NULL; - grpc_error *err = GRPC_ERROR_NONE; - if (requested_port == 0) { - /* Note: There could be a race where some local addrs can listen on the - selected port and some can't. The sane way to handle this would be to - retry by recreating the whole grpc_tcp_server. Backing out individual - listeners and orphaning the FDs looks like too much trouble. */ - if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) { - return err; - } else if (requested_port <= 0) { - return GRPC_ERROR_CREATE("Bad get_unused_port()"); - } - gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port); - } - if (getifaddrs(&ifa) != 0 || ifa == NULL) { - return GRPC_OS_ERROR(errno, "getifaddrs"); - } - for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) { - grpc_resolved_address addr; - char *addr_str = NULL; - grpc_dualstack_mode dsmode; - grpc_tcp_listener *new_sp = NULL; - const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>"); - if (ifa_it->ifa_addr == NULL) { - continue; - } else if (ifa_it->ifa_addr->sa_family == AF_INET) { - addr.len = sizeof(struct sockaddr_in); - } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { - addr.len = sizeof(struct sockaddr_in6); - } else { - continue; - } - memcpy(addr.addr, ifa_it->ifa_addr, addr.len); - if (!grpc_sockaddr_set_port(&addr, requested_port)) { - /* Should never happen, because we check sa_family above. */ - err = GRPC_ERROR_CREATE("Failed to set port"); - break; - } - if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) { - addr_str = gpr_strdup("<error>"); - } - gpr_log(GPR_DEBUG, - "Adding local addr from interface %s flags 0x%x to server: %s", - ifa_name, ifa_it->ifa_flags, addr_str); - /* We could have multiple interfaces with the same address (e.g., bonding), - so look for duplicates. */ - if (find_listener_with_addr(s, &addr) != NULL) { - gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str, - ifa_name); - gpr_free(addr_str); - continue; - } - if ((err = add_addr_to_server(s, &addr, port_index, fd_index, &dsmode, - &new_sp)) != GRPC_ERROR_NONE) { - char *err_str = NULL; - grpc_error *root_err; - if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) { - err_str = gpr_strdup("Failed to add listener"); - } - root_err = GRPC_ERROR_CREATE(err_str); - gpr_free(err_str); - gpr_free(addr_str); - err = grpc_error_add_child(root_err, err); - break; - } else { - GPR_ASSERT(requested_port == new_sp->port); - ++fd_index; - if (sp != NULL) { - new_sp->is_sibling = 1; - sp->sibling = new_sp; - } - sp = new_sp; - } - gpr_free(addr_str); - } - freeifaddrs(ifa); - if (err != GRPC_ERROR_NONE) { - return err; - } else if (sp == NULL) { - return GRPC_ERROR_CREATE("No local addresses"); - } else { - *out_port = sp->port; - return GRPC_ERROR_NONE; - } -} - /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, unsigned port_index, @@ -701,14 +323,16 @@ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, grpc_error *v6_err = GRPC_ERROR_NONE; grpc_error *v4_err = GRPC_ERROR_NONE; *out_port = -1; - if (s->expand_wildcard_addrs) { - return add_all_local_addrs_to_server(s, port_index, requested_port, - out_port); + + if (grpc_tcp_server_have_ifaddrs() && s->expand_wildcard_addrs) { + return grpc_tcp_server_add_all_local_addrs(s, port_index, requested_port, + out_port); } + grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6); /* Try listening on IPv6 first. */ - if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode, - &sp)) == GRPC_ERROR_NONE) { + if ((v6_err = grpc_tcp_server_add_addr(s, &wild6, port_index, fd_index, + &dsmode, &sp)) == GRPC_ERROR_NONE) { ++fd_index; requested_port = *out_port = sp->port; if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) { @@ -717,8 +341,8 @@ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, } /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */ grpc_sockaddr_set_port(&wild4, requested_port); - if ((v4_err = add_addr_to_server(s, &wild4, port_index, fd_index, &dsmode, - &sp2)) == GRPC_ERROR_NONE) { + if ((v4_err = grpc_tcp_server_add_addr(s, &wild4, port_index, fd_index, + &dsmode, &sp2)) == GRPC_ERROR_NONE) { *out_port = sp2->port; if (sp != NULL) { sp2->is_sibling = 1; @@ -726,8 +350,20 @@ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, } } if (*out_port > 0) { - GRPC_LOG_IF_ERROR("Failed to add :: listener", v6_err); - GRPC_LOG_IF_ERROR("Failed to add 0.0.0.0 listener", v4_err); + if (v6_err != GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, + "Failed to add :: listener, " + "the environment may not support IPv6: %s", + grpc_error_string(v6_err)); + GRPC_ERROR_UNREF(v6_err); + } + if (v4_err != GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, + "Failed to add 0.0.0.0 listener, " + "the environment may not support IPv4: %s", + grpc_error_string(v4_err)); + GRPC_ERROR_UNREF(v4_err); + } return GRPC_ERROR_NONE; } else { grpc_error *root_err = @@ -756,7 +392,7 @@ static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) { err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode, &fd); if (err != GRPC_ERROR_NONE) return err; - err = prepare_socket(fd, &listener->addr, true, &port); + err = grpc_tcp_server_prepare_socket(fd, &listener->addr, true, &port); if (err != GRPC_ERROR_NONE) return err; listener->server->nports++; grpc_sockaddr_to_string(&addr_str, &listener->addr, 1); @@ -828,7 +464,7 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } - if ((err = add_addr_to_server(s, addr, port_index, 0, &dsmode, &sp)) == + if ((err = grpc_tcp_server_add_addr(s, addr, port_index, 0, &dsmode, &sp)) == GRPC_ERROR_NONE) { *out_port = sp->port; } diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h new file mode 100644 index 0000000000..f5dc8532f9 --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix.h @@ -0,0 +1,134 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H +#define GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" +#include "src/core/lib/iomgr/tcp_server.h" + +/* one listening port */ +typedef struct grpc_tcp_listener { + int fd; + grpc_fd *emfd; + grpc_tcp_server *server; + grpc_resolved_address addr; + int port; + unsigned port_index; + unsigned fd_index; + grpc_closure read_closure; + grpc_closure destroyed_closure; + struct grpc_tcp_listener *next; + /* sibling is a linked list of all listeners for a given port. add_port and + clone_port place all new listeners in the same sibling list. A member of + the 'sibling' list is also a member of the 'next' list. The head of each + sibling list has is_sibling==0, and subsequent members of sibling lists + have is_sibling==1. is_sibling allows separate sibling lists to be + identified while iterating through 'next'. */ + struct grpc_tcp_listener *sibling; + int is_sibling; +} grpc_tcp_listener; + +/* the overall server */ +struct grpc_tcp_server { + gpr_refcount refs; + /* Called whenever accept() succeeds on a server port. */ + grpc_tcp_server_cb on_accept_cb; + void *on_accept_cb_arg; + + gpr_mu mu; + + /* active port count: how many ports are actually still listening */ + size_t active_ports; + /* destroyed port count: how many ports are completely destroyed */ + size_t destroyed_ports; + + /* is this server shutting down? */ + bool shutdown; + /* have listeners been shutdown? */ + bool shutdown_listeners; + /* use SO_REUSEPORT */ + bool so_reuseport; + /* expand wildcard addresses to a list of all local addresses */ + bool expand_wildcard_addrs; + + /* linked list of server ports */ + grpc_tcp_listener *head; + grpc_tcp_listener *tail; + unsigned nports; + + /* List of closures passed to shutdown_starting_add(). */ + grpc_closure_list shutdown_starting; + + /* shutdown callback */ + grpc_closure *shutdown_complete; + + /* all pollsets interested in new connections */ + grpc_pollset **pollsets; + /* number of pollsets in the pollsets array */ + size_t pollset_count; + + /* next pollset to assign a channel to */ + gpr_atm next_pollset_to_assign; + + grpc_resource_quota *resource_quota; +}; + +/* If successful, add a listener to \a s for \a addr, set \a dsmode for the + socket, and return the \a listener. */ +grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, + const grpc_resolved_address *addr, + unsigned port_index, unsigned fd_index, + grpc_dualstack_mode *dsmode, + grpc_tcp_listener **listener); + +/* Get all addresses assigned to network interfaces on the machine and create a + listener for each. requested_port is the port to use for every listener, or 0 + to select one random port that will be used for every listener. Set *out_port + to the port selected. Return GRPC_ERROR_NONE only if all listeners were + added. */ +grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, + unsigned port_index, + int requested_port, + int *out_port); + +/* Prepare a recently-created socket for listening. */ +grpc_error *grpc_tcp_server_prepare_socket(int fd, + const grpc_resolved_address *addr, + bool so_reuseport, int *port); +/* Ruturn true if the platform supports ifaddrs */ +bool grpc_tcp_server_have_ifaddrs(void); + +#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H */ diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.c b/src/core/lib/iomgr/tcp_server_utils_posix_common.c new file mode 100644 index 0000000000..e45e27d5ab --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.c @@ -0,0 +1,220 @@ +/* + * + * Copyright 2017, 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/iomgr/port.h" + +#ifdef GRPC_HAVE_IFADDRS + +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/sync.h> + +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/unix_sockets_posix.h" + +#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 + +static gpr_once s_init_max_accept_queue_size; +static int s_max_accept_queue_size; + +/* get max listen queue size on linux */ +static void init_max_accept_queue_size(void) { + int n = SOMAXCONN; + char buf[64]; + FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r"); + if (fp == NULL) { + /* 2.4 kernel. */ + s_max_accept_queue_size = SOMAXCONN; + return; + } + if (fgets(buf, sizeof buf, fp)) { + char *end; + long i = strtol(buf, &end, 10); + if (i > 0 && i <= INT_MAX && end && *end == 0) { + n = (int)i; + } + } + fclose(fp); + s_max_accept_queue_size = n; + + if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) { + gpr_log(GPR_INFO, + "Suspiciously small accept queue (%d) will probably lead to " + "connection drops", + s_max_accept_queue_size); + } +} + +static int get_max_accept_queue_size(void) { + gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size); + return s_max_accept_queue_size; +} + +static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd, + const grpc_resolved_address *addr, + unsigned port_index, unsigned fd_index, + grpc_tcp_listener **listener) { + grpc_tcp_listener *sp = NULL; + int port = -1; + char *addr_str; + char *name; + + grpc_error *err = + grpc_tcp_server_prepare_socket(fd, addr, s->so_reuseport, &port); + if (err == GRPC_ERROR_NONE) { + GPR_ASSERT(port > 0); + grpc_sockaddr_to_string(&addr_str, addr, 1); + gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); + gpr_mu_lock(&s->mu); + s->nports++; + GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); + sp = gpr_malloc(sizeof(grpc_tcp_listener)); + sp->next = NULL; + if (s->head == NULL) { + s->head = sp; + } else { + s->tail->next = sp; + } + s->tail = sp; + sp->server = s; + sp->fd = fd; + sp->emfd = grpc_fd_create(fd, name); + memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); + sp->port = port; + sp->port_index = port_index; + sp->fd_index = fd_index; + sp->is_sibling = 0; + sp->sibling = NULL; + GPR_ASSERT(sp->emfd); + gpr_mu_unlock(&s->mu); + gpr_free(addr_str); + gpr_free(name); + } + + *listener = sp; + return err; +} + +/* If successful, add a listener to s for addr, set *dsmode for the socket, and + return the *listener. */ +grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, + const grpc_resolved_address *addr, + unsigned port_index, unsigned fd_index, + grpc_dualstack_mode *dsmode, + grpc_tcp_listener **listener) { + grpc_resolved_address addr4_copy; + int fd; + grpc_error *err = + grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd); + if (err != GRPC_ERROR_NONE) { + return err; + } + if (*dsmode == GRPC_DSMODE_IPV4 && + grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { + addr = &addr4_copy; + } + return add_socket_to_server(s, fd, addr, port_index, fd_index, listener); +} + +/* Prepare a recently-created socket for listening. */ +grpc_error *grpc_tcp_server_prepare_socket(int fd, + const grpc_resolved_address *addr, + bool so_reuseport, int *port) { + grpc_resolved_address sockname_temp; + grpc_error *err = GRPC_ERROR_NONE; + + GPR_ASSERT(fd >= 0); + + if (so_reuseport && !grpc_is_unix_socket(addr)) { + err = grpc_set_socket_reuse_port(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + } + + err = grpc_set_socket_nonblocking(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_cloexec(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + if (!grpc_is_unix_socket(addr)) { + err = grpc_set_socket_low_latency(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_reuse_addr(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + } + err = grpc_set_socket_no_sigpipe_if_possible(fd); + if (err != GRPC_ERROR_NONE) goto error; + + GPR_ASSERT(addr->len < ~(socklen_t)0); + if (bind(fd, (struct sockaddr *)addr->addr, (socklen_t)addr->len) < 0) { + err = GRPC_OS_ERROR(errno, "bind"); + goto error; + } + + if (listen(fd, get_max_accept_queue_size()) < 0) { + err = GRPC_OS_ERROR(errno, "listen"); + goto error; + } + + sockname_temp.len = sizeof(struct sockaddr_storage); + + if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, + (socklen_t *)&sockname_temp.len) < 0) { + err = GRPC_OS_ERROR(errno, "getsockname"); + goto error; + } + + *port = grpc_sockaddr_get_port(&sockname_temp); + return GRPC_ERROR_NONE; + +error: + GPR_ASSERT(err != GRPC_ERROR_NONE); + if (fd >= 0) { + close(fd); + } + grpc_error *ret = grpc_error_set_int( + GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1), + GRPC_ERROR_INT_FD, fd); + GRPC_ERROR_UNREF(err); + return ret; +} + +#endif /* GRPC_HAVE_IFADDRS */ diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c new file mode 100644 index 0000000000..6354a6bdc1 --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c @@ -0,0 +1,195 @@ +/* + * + * Copyright 2017, 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/iomgr/port.h" + +#ifdef GRPC_HAVE_IFADDRS + +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" + +#include <errno.h> +#include <ifaddrs.h> +#include <stddef.h> +#include <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> + +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" + +/* Return the listener in s with address addr or NULL. */ +static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s, + grpc_resolved_address *addr) { + grpc_tcp_listener *l; + gpr_mu_lock(&s->mu); + for (l = s->head; l != NULL; l = l->next) { + if (l->addr.len != addr->len) { + continue; + } + if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) { + break; + } + } + gpr_mu_unlock(&s->mu); + return l; +} + +/* Bind to "::" to get a port number not used by any address. */ +static grpc_error *get_unused_port(int *port) { + grpc_resolved_address wild; + grpc_sockaddr_make_wildcard6(0, &wild); + grpc_dualstack_mode dsmode; + int fd; + grpc_error *err = + grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd); + if (err != GRPC_ERROR_NONE) { + return err; + } + if (dsmode == GRPC_DSMODE_IPV4) { + grpc_sockaddr_make_wildcard4(0, &wild); + } + if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) { + err = GRPC_OS_ERROR(errno, "bind"); + close(fd); + return err; + } + if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) != + 0) { + err = GRPC_OS_ERROR(errno, "getsockname"); + close(fd); + return err; + } + close(fd); + *port = grpc_sockaddr_get_port(&wild); + return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE; +} + +grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, + unsigned port_index, + int requested_port, + int *out_port) { + struct ifaddrs *ifa = NULL; + struct ifaddrs *ifa_it; + unsigned fd_index = 0; + grpc_tcp_listener *sp = NULL; + grpc_error *err = GRPC_ERROR_NONE; + if (requested_port == 0) { + /* Note: There could be a race where some local addrs can listen on the + selected port and some can't. The sane way to handle this would be to + retry by recreating the whole grpc_tcp_server. Backing out individual + listeners and orphaning the FDs looks like too much trouble. */ + if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) { + return err; + } else if (requested_port <= 0) { + return GRPC_ERROR_CREATE("Bad get_unused_port()"); + } + gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port); + } + if (getifaddrs(&ifa) != 0 || ifa == NULL) { + return GRPC_OS_ERROR(errno, "getifaddrs"); + } + for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) { + grpc_resolved_address addr; + char *addr_str = NULL; + grpc_dualstack_mode dsmode; + grpc_tcp_listener *new_sp = NULL; + const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>"); + if (ifa_it->ifa_addr == NULL) { + continue; + } else if (ifa_it->ifa_addr->sa_family == AF_INET) { + addr.len = sizeof(struct sockaddr_in); + } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { + addr.len = sizeof(struct sockaddr_in6); + } else { + continue; + } + memcpy(addr.addr, ifa_it->ifa_addr, addr.len); + if (!grpc_sockaddr_set_port(&addr, requested_port)) { + /* Should never happen, because we check sa_family above. */ + err = GRPC_ERROR_CREATE("Failed to set port"); + break; + } + if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) { + addr_str = gpr_strdup("<error>"); + } + gpr_log(GPR_DEBUG, + "Adding local addr from interface %s flags 0x%x to server: %s", + ifa_name, ifa_it->ifa_flags, addr_str); + /* We could have multiple interfaces with the same address (e.g., bonding), + so look for duplicates. */ + if (find_listener_with_addr(s, &addr) != NULL) { + gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str, + ifa_name); + gpr_free(addr_str); + continue; + } + if ((err = grpc_tcp_server_add_addr(s, &addr, port_index, fd_index, &dsmode, + &new_sp)) != GRPC_ERROR_NONE) { + char *err_str = NULL; + grpc_error *root_err; + if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) { + err_str = gpr_strdup("Failed to add listener"); + } + root_err = GRPC_ERROR_CREATE(err_str); + gpr_free(err_str); + gpr_free(addr_str); + err = grpc_error_add_child(root_err, err); + break; + } else { + GPR_ASSERT(requested_port == new_sp->port); + ++fd_index; + if (sp != NULL) { + new_sp->is_sibling = 1; + sp->sibling = new_sp; + } + sp = new_sp; + } + gpr_free(addr_str); + } + freeifaddrs(ifa); + if (err != GRPC_ERROR_NONE) { + return err; + } else if (sp == NULL) { + return GRPC_ERROR_CREATE("No local addresses"); + } else { + *out_port = sp->port; + return GRPC_ERROR_NONE; + } +} + +bool grpc_tcp_server_have_ifaddrs(void) { return true; } + +#endif /* GRPC_HAVE_IFADDRS */ diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c new file mode 100644 index 0000000000..95c3198be6 --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c @@ -0,0 +1,49 @@ +/* + * + * Copyright 2017, 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/iomgr/port.h" + +#if defined(GRPC_POSIX_SOCKET) && !defined(GRPC_HAVE_IFADDRS) + +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" + +grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, + unsigned port_index, + int requested_port, + int *out_port) { + return GRPC_ERROR_CREATE("no ifaddrs available"); +} + +bool grpc_tcp_server_have_ifaddrs(void) { return false; } + +#endif /* defined(GRPC_POSIX_SOCKET) && !defined(GRPC_HAVE_IFADDRS) */ diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index 2a1c8d39fa..71e295770a 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -109,8 +109,8 @@ struct grpc_udp_server { grpc_pollset **pollsets; /* number of pollsets in the pollsets array */ size_t pollset_count; - /* The parent grpc server */ - grpc_server *grpc_server; + /* opaque object to pass to callbacks */ + void *user_data; }; grpc_udp_server *grpc_udp_server_create(void) { @@ -178,7 +178,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { /* Call the orphan_cb to signal that the FD is about to be closed and * should no longer be used. */ GPR_ASSERT(sp->orphan_cb); - sp->orphan_cb(exec_ctx, sp->emfd); + sp->orphan_cb(exec_ctx, sp->emfd, sp->server->user_data); grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL, "udp_listener_shutdown"); @@ -204,7 +204,7 @@ void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, if (s->active_ports) { for (sp = s->head; sp; sp = sp->next) { GPR_ASSERT(sp->orphan_cb); - sp->orphan_cb(exec_ctx, sp->emfd); + sp->orphan_cb(exec_ctx, sp->emfd, sp->server->user_data); grpc_fd_shutdown(exec_ctx, sp->emfd, GRPC_ERROR_CREATE("Server destroyed")); } @@ -299,7 +299,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { /* Tell the registered callback that data is available to read. */ GPR_ASSERT(sp->read_cb); - sp->read_cb(exec_ctx, sp->emfd, sp->server->grpc_server); + sp->read_cb(exec_ctx, sp->emfd, sp->server->user_data); /* Re-arm the notification event so we get another chance to read. */ grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); @@ -322,7 +322,7 @@ static void on_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { /* Tell the registered callback that the socket is writeable. */ GPR_ASSERT(sp->write_cb); - sp->write_cb(exec_ctx, sp->emfd); + sp->write_cb(exec_ctx, sp->emfd, sp->server->user_data); /* Re-arm the notification event so we get another chance to write. */ grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure); @@ -464,13 +464,13 @@ int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index) { void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, grpc_pollset **pollsets, size_t pollset_count, - grpc_server *server) { + void *user_data) { size_t i; gpr_mu_lock(&s->mu); grpc_udp_listener *sp; GPR_ASSERT(s->active_ports == 0); s->pollsets = pollsets; - s->grpc_server = server; + s->user_data = user_data; sp = s->head; while (sp != NULL) { @@ -485,7 +485,11 @@ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, grpc_schedule_on_exec_ctx); grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure); - s->active_ports++; + /* Registered for both read and write callbacks: increment active_ports + * twice to account for this, and delay free-ing of memory until both + * on_read and on_write have fired. */ + s->active_ports += 2; + sp = sp->next; } diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h index ed63fa7d81..90842a47f0 100644 --- a/src/core/lib/iomgr/udp_server.h +++ b/src/core/lib/iomgr/udp_server.h @@ -47,23 +47,23 @@ typedef struct grpc_udp_server grpc_udp_server; /* Called when data is available to read from the socket. */ typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, - struct grpc_server *server); + void *user_data); /* Called when the socket is writeable. */ -typedef void (*grpc_udp_server_write_cb)(grpc_exec_ctx *exec_ctx, - grpc_fd *emfd); +typedef void (*grpc_udp_server_write_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, + void *user_data); /* Called when the grpc_fd is about to be orphaned (and the FD closed). */ typedef void (*grpc_udp_server_orphan_cb)(grpc_exec_ctx *exec_ctx, - grpc_fd *emfd); + grpc_fd *emfd, void *user_data); /* Create a server, initially not bound to any ports */ grpc_udp_server *grpc_udp_server_create(void); -/* Start listening to bound ports */ +/* Start listening to bound ports. user_data is passed to callbacks. */ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server, grpc_pollset **pollsets, size_t pollset_count, - struct grpc_server *server); + void *user_data); int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index); diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h index 71d32d97ba..c8dd242c75 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.h +++ b/src/core/lib/iomgr/wakeup_fd_posix.h @@ -46,7 +46,7 @@ * * Setup: * 1. Before calling anything, call global_init() at least once. - * 1. Call grpc_wakeup_fd_create() to get a wakeup_fd. + * 1. Call grpc_wakeup_fd_init() to set up a wakeup_fd. * 2. Add the result of GRPC_WAKEUP_FD_FD to the set of monitored file * descriptors for the poll() style API you are using. Monitor the file * descriptor for readability. diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index a23082a866..8dea1d98ff 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -318,7 +318,7 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { call_data *calld = elem->call_data; grpc_call_credentials_unref(exec_ctx, calld->creds); if (calld->have_host) { diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c index 14619d97ca..01cb473177 100644 --- a/src/core/lib/security/transport/server_auth_filter.c +++ b/src/core/lib/security/transport/server_auth_filter.c @@ -227,7 +227,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) {} + grpc_closure *ignored) {} /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/support/arena.c b/src/core/lib/support/arena.c new file mode 100644 index 0000000000..7bcb983f24 --- /dev/null +++ b/src/core/lib/support/arena.c @@ -0,0 +1,98 @@ +/* + * + * Copyright 2017, 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/support/arena.h" +#include <grpc/support/alloc.h> +#include <grpc/support/atm.h> +#include <grpc/support/log.h> +#include <grpc/support/useful.h> + +#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \ + (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u)) + +typedef struct zone { + size_t size_begin; + size_t size_end; + gpr_atm next_atm; +} zone; + +struct gpr_arena { + gpr_atm size_so_far; + zone initial_zone; +}; + +gpr_arena *gpr_arena_create(size_t initial_size) { + initial_size = ROUND_UP_TO_ALIGNMENT_SIZE(initial_size); + gpr_arena *a = gpr_zalloc(sizeof(gpr_arena) + initial_size); + a->initial_zone.size_end = initial_size; + return a; +} + +size_t gpr_arena_destroy(gpr_arena *arena) { + gpr_atm size = gpr_atm_no_barrier_load(&arena->size_so_far); + zone *z = (zone *)gpr_atm_no_barrier_load(&arena->initial_zone.next_atm); + gpr_free(arena); + while (z) { + zone *next_z = (zone *)gpr_atm_no_barrier_load(&z->next_atm); + gpr_free(z); + z = next_z; + } + return (size_t)size; +} + +void *gpr_arena_alloc(gpr_arena *arena, size_t size) { + size = ROUND_UP_TO_ALIGNMENT_SIZE(size); + size_t start = + (size_t)gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size); + zone *z = &arena->initial_zone; + while (start > z->size_end) { + zone *next_z = (zone *)gpr_atm_acq_load(&z->next_atm); + if (next_z == NULL) { + size_t next_z_size = (size_t)gpr_atm_no_barrier_load(&arena->size_so_far); + next_z = gpr_zalloc(sizeof(zone) + next_z_size); + next_z->size_begin = z->size_end; + next_z->size_end = z->size_end + next_z_size; + if (!gpr_atm_rel_cas(&z->next_atm, (gpr_atm)NULL, (gpr_atm)next_z)) { + gpr_free(next_z); + next_z = (zone *)gpr_atm_acq_load(&z->next_atm); + } + } + z = next_z; + } + if (start + size > z->size_end) { + return gpr_arena_alloc(arena, size); + } + GPR_ASSERT(start >= z->size_begin); + GPR_ASSERT(start + size <= z->size_end); + return ((char *)(z + 1)) + start - z->size_begin; +} diff --git a/src/core/lib/support/arena.h b/src/core/lib/support/arena.h new file mode 100644 index 0000000000..c28033ffc3 --- /dev/null +++ b/src/core/lib/support/arena.h @@ -0,0 +1,54 @@ +/* + * + * Copyright 2017, 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. + * + */ + +// \file Arena based allocator +// Allows very fast allocation of memory, but that memory cannot be freed until +// the arena as a whole is freed +// Tracks the total memory allocated against it, so that future arenas can +// pre-allocate the right amount of memory + +#ifndef GRPC_CORE_LIB_SUPPORT_ARENA_H +#define GRPC_CORE_LIB_SUPPORT_ARENA_H + +#include <stddef.h> + +typedef struct gpr_arena gpr_arena; + +// Create an arena, with \a initial_size bytes in the first allocated buffer +gpr_arena *gpr_arena_create(size_t initial_size); +// Allocate \a size bytes from the arena +void *gpr_arena_alloc(gpr_arena *arena, size_t size); +// Destroy an arena, returning the total number of bytes allocated +size_t gpr_arena_destroy(gpr_arena *arena); + +#endif /* GRPC_CORE_LIB_SUPPORT_ARENA_H */ diff --git a/src/core/lib/support/sync.c b/src/core/lib/support/sync.c index e4a7fce646..b52f004f74 100644 --- a/src/core/lib/support/sync.c +++ b/src/core/lib/support/sync.c @@ -119,6 +119,10 @@ int gpr_unref(gpr_refcount *r) { return prior == 1; } +int gpr_ref_is_unique(gpr_refcount *r) { + return gpr_atm_acq_load(&r->count) == 1; +} + void gpr_stats_init(gpr_stats_counter *c, intptr_t n) { gpr_atm_rel_store(&c->value, n); } diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index c2547c5147..2c5d8c0ff3 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -51,6 +51,7 @@ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/arena.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" @@ -138,14 +139,15 @@ typedef struct batch_control { } batch_control; struct grpc_call { + gpr_arena *arena; grpc_completion_queue *cq; grpc_polling_entity pollent; grpc_channel *channel; grpc_call *parent; grpc_call *first_child; gpr_timespec start_time; - /* TODO(ctiller): share with cq if possible? */ - gpr_mu mu; + /* protects first_child, and child next/prev links */ + gpr_mu child_list_mu; /* client or server call */ bool is_client; @@ -160,8 +162,8 @@ struct grpc_call { bool received_initial_metadata; bool receiving_message; bool requested_final_op; - bool received_final_op; - bool sent_any_op; + gpr_atm any_ops_sent_atm; + gpr_atm received_final_op_atm; /* have we received initial metadata */ bool has_initial_md_been_received; @@ -212,6 +214,8 @@ struct grpc_call { grpc_closure receiving_initial_metadata_ready; uint32_t test_only_last_message_flags; + grpc_closure release_call; + union { struct { grpc_status_code *status; @@ -273,9 +277,13 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, grpc_channel_get_channel_stack(args->channel); grpc_call *call; GPR_TIMER_BEGIN("grpc_call_create", 0); - call = gpr_zalloc(sizeof(grpc_call) + channel_stack->call_stack_size); + gpr_arena *arena = + gpr_arena_create(grpc_channel_get_call_size_estimate(args->channel)); + call = gpr_arena_alloc(arena, + sizeof(grpc_call) + channel_stack->call_stack_size); + call->arena = arena; *out_call = call; - gpr_mu_init(&call->mu); + gpr_mu_init(&call->child_list_mu); call->channel = args->channel; call->cq = args->cq; call->parent = args->parent_call; @@ -313,7 +321,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, GPR_ASSERT(call->is_client); GPR_ASSERT(!args->parent_call->is_client); - gpr_mu_lock(&args->parent_call->mu); + gpr_mu_lock(&args->parent_call->child_list_mu); if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) { send_deadline = gpr_time_min( @@ -341,6 +349,10 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, } if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) { call->cancellation_is_inherited = 1; + if (gpr_atm_acq_load(&args->parent_call->received_final_op_atm)) { + cancel_with_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE, + GRPC_ERROR_CANCELLED); + } } if (args->parent_call->first_child == NULL) { @@ -353,18 +365,23 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, call; } - gpr_mu_unlock(&args->parent_call->mu); + gpr_mu_unlock(&args->parent_call->child_list_mu); } call->send_deadline = send_deadline; GRPC_CHANNEL_INTERNAL_REF(args->channel, "call"); /* initial refcount dropped by grpc_call_destroy */ + grpc_call_element_args call_args = { + .call_stack = CALL_STACK_FROM_CALL(call), + .server_transport_data = args->server_transport_data, + .context = call->context, + .path = path, + .start_time = call->start_time, + .deadline = send_deadline, + .arena = call->arena}; add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1, - destroy_call, call, call->context, - args->server_transport_data, path, - call->start_time, send_deadline, - CALL_STACK_FROM_CALL(call))); + destroy_call, call, &call_args)); if (error != GRPC_ERROR_NONE) { cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); @@ -421,6 +438,14 @@ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) { GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON); } +static void release_call(grpc_exec_ctx *exec_ctx, void *call, + grpc_error *error) { + grpc_call *c = call; + grpc_channel *channel = c->channel; + grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena)); + GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call"); +} + static void set_status_value_directly(grpc_status_code status, void *dest); static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { @@ -435,7 +460,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, if (c->receiving_stream != NULL) { grpc_byte_stream_destroy(exec_ctx, c->receiving_stream); } - gpr_mu_destroy(&c->mu); + gpr_mu_destroy(&c->child_list_mu); for (ii = 0; ii < c->send_extra_metadata_count; ii++) { GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md); } @@ -447,7 +472,6 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, if (c->cq) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } - grpc_channel *channel = c->channel; get_final_status(call, set_status_value_directly, &c->final_info.final_status, NULL); @@ -456,11 +480,12 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, for (i = 0; i < STATUS_SOURCE_COUNT; i++) { GRPC_ERROR_UNREF( - unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error); + unpack_received_status(gpr_atm_acq_load(&c->status[i])).error); } - grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c); - GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call"); + grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, + grpc_closure_init(&c->release_call, release_call, c, + grpc_schedule_on_exec_ctx)); GPR_TIMER_END("destroy_call", 0); } @@ -473,7 +498,7 @@ void grpc_call_destroy(grpc_call *c) { GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c)); if (parent) { - gpr_mu_lock(&parent->mu); + gpr_mu_lock(&parent->child_list_mu); if (c == parent->first_child) { parent->first_child = c->sibling_next; if (c == parent->first_child) { @@ -482,15 +507,14 @@ void grpc_call_destroy(grpc_call *c) { c->sibling_prev->sibling_next = c->sibling_next; c->sibling_next->sibling_prev = c->sibling_prev; } - gpr_mu_unlock(&parent->mu); + gpr_mu_unlock(&parent->child_list_mu); GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child"); } - gpr_mu_lock(&c->mu); GPR_ASSERT(!c->destroy_called); c->destroy_called = 1; - cancel = c->sent_any_op && !c->received_final_op; - gpr_mu_unlock(&c->mu); + cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) && + !gpr_atm_acq_load(&c->received_final_op_atm); if (cancel) { cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); @@ -555,53 +579,25 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c, "c=%p, status=%d, description=%s, reserved=%p)", 4, (c, (int)status, description, reserved)); GPR_ASSERT(reserved == NULL); - gpr_mu_lock(&c->mu); cancel_with_status(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, status, description); - gpr_mu_unlock(&c->mu); grpc_exec_ctx_finish(&exec_ctx); return GRPC_CALL_OK; } -typedef struct termination_closure { - grpc_closure closure; - grpc_call *call; - grpc_transport_stream_op op; -} termination_closure; - -static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, +static void done_termination(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { - termination_closure *tc = tcp; - GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "termination"); - gpr_free(tc); -} - -static void send_termination(grpc_exec_ctx *exec_ctx, void *tcp, - grpc_error *error) { - termination_closure *tc = tcp; - memset(&tc->op, 0, sizeof(tc->op)); - tc->op.cancel_error = GRPC_ERROR_REF(error); - /* reuse closure to catch completion */ - tc->op.on_complete = grpc_closure_init(&tc->closure, done_termination, tc, - grpc_schedule_on_exec_ctx); - execute_op(exec_ctx, tc->call, &tc->op); -} - -static void terminate_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c, - grpc_error *error) { - termination_closure *tc = gpr_malloc(sizeof(*tc)); - memset(tc, 0, sizeof(*tc)); - tc->call = c; - GRPC_CALL_INTERNAL_REF(tc->call, "termination"); - grpc_closure_sched(exec_ctx, grpc_closure_init(&tc->closure, send_termination, - tc, grpc_schedule_on_exec_ctx), - error); + GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "termination"); } static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c, status_source source, grpc_error *error) { + GRPC_CALL_INTERNAL_REF(c, "termination"); set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error)); - terminate_with_error(exec_ctx, c, error); + grpc_transport_stream_op *op = grpc_make_transport_stream_op( + grpc_closure_create(done_termination, c, grpc_schedule_on_exec_ctx)); + op->cancel_error = error; + execute_op(exec_ctx, c, op); } static grpc_error *error_from_status(grpc_status_code status, @@ -715,9 +711,7 @@ static void set_incoming_compression_algorithm( grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm( grpc_call *call) { grpc_compression_algorithm algorithm; - gpr_mu_lock(&call->mu); algorithm = call->incoming_compression_algorithm; - gpr_mu_unlock(&call->mu); return algorithm; } @@ -729,9 +723,7 @@ static grpc_compression_algorithm compression_algorithm_for_level_locked( uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) { uint32_t flags; - gpr_mu_lock(&call->mu); flags = call->test_only_last_message_flags; - gpr_mu_unlock(&call->mu); return flags; } @@ -785,9 +777,7 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx, uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) { uint32_t encodings_accepted_by_peer; - gpr_mu_lock(&call->mu); encodings_accepted_by_peer = call->encodings_accepted_by_peer; - gpr_mu_unlock(&call->mu); return encodings_accepted_by_peer; } @@ -1056,7 +1046,7 @@ static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data, } static grpc_error *consolidate_batch_errors(batch_control *bctl) { - size_t n = (size_t)gpr_atm_no_barrier_load(&bctl->num_errors); + size_t n = (size_t)gpr_atm_acq_load(&bctl->num_errors); if (n == 0) { return GRPC_ERROR_NONE; } else if (n == 1) { @@ -1083,8 +1073,6 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx, grpc_call *call = bctl->call; grpc_error *error = consolidate_batch_errors(bctl); - gpr_mu_lock(&call->mu); - if (bctl->send_initial_metadata) { grpc_metadata_batch_destroy( exec_ctx, @@ -1103,20 +1091,23 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx, &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; recv_trailing_filter(exec_ctx, call, md); - call->received_final_op = true; /* propagate cancellation to any interested children */ + gpr_atm_rel_store(&call->received_final_op_atm, 1); + gpr_mu_lock(&call->child_list_mu); child_call = call->first_child; if (child_call != NULL) { do { next_child_call = child_call->sibling_next; if (child_call->cancellation_is_inherited) { GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel"); - grpc_call_cancel(child_call, NULL); + cancel_with_error(exec_ctx, child_call, STATUS_FROM_API_OVERRIDE, + GRPC_ERROR_CANCELLED); GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel"); } child_call = next_child_call; } while (child_call != call->first_child); } + gpr_mu_unlock(&call->child_list_mu); if (call->is_client) { get_final_status(call, set_status_value_directly, @@ -1130,7 +1121,6 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx, GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } - gpr_mu_unlock(&call->mu); if (bctl->is_notify_tag_closure) { /* unrefs bctl->error */ @@ -1221,7 +1211,6 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error) { batch_control *bctl = bctlp; grpc_call *call = bctl->call; - gpr_mu_lock(&bctl->call->mu); if (error != GRPC_ERROR_NONE) { if (call->receiving_stream != NULL) { grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); @@ -1233,11 +1222,9 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp, } if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE || call->receiving_stream == NULL) { - gpr_mu_unlock(&bctl->call->mu); process_data_after_md(exec_ctx, bctlp); } else { call->saved_receiving_stream_ready_bctlp = bctlp; - gpr_mu_unlock(&bctl->call->mu); } } @@ -1296,7 +1283,7 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx, static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, grpc_error *error, bool has_cancelled) { if (error == GRPC_ERROR_NONE) return; - int idx = (int)gpr_atm_no_barrier_fetch_add(&bctl->num_errors, 1); + int idx = (int)gpr_atm_full_fetch_add(&bctl->num_errors, 1); if (idx == 0 && !has_cancelled) { cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE, GRPC_ERROR_REF(error)); @@ -1309,8 +1296,6 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx, batch_control *bctl = bctlp; grpc_call *call = bctl->call; - gpr_mu_lock(&call->mu); - add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { grpc_metadata_batch *md = @@ -1336,11 +1321,9 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx, receiving_stream_ready, call->saved_receiving_stream_ready_bctlp, grpc_schedule_on_exec_ctx); call->saved_receiving_stream_ready_bctlp = NULL; - grpc_closure_sched(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error)); + grpc_closure_run(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error)); } - gpr_mu_unlock(&call->mu); - finish_batch_step(exec_ctx, bctl); } @@ -1393,7 +1376,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->notify_tag = notify_tag; bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0); - gpr_mu_lock(&call->mu); grpc_transport_stream_op *stream_op = &bctl->op; memset(stream_op, 0, sizeof(*stream_op)); stream_op->covered_by_poller = true; @@ -1679,8 +1661,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_closure_init(&bctl->finish_batch, finish_batch, bctl, grpc_schedule_on_exec_ctx); stream_op->on_complete = &bctl->finish_batch; - call->sent_any_op = true; - gpr_mu_unlock(&call->mu); + gpr_atm_rel_store(&call->any_ops_sent_atm, 1); execute_op(exec_ctx, call, stream_op); @@ -1711,7 +1692,6 @@ done_with_error: if (bctl->recv_final_op) { call->requested_final_op = 0; } - gpr_mu_unlock(&call->mu); goto done; } @@ -1760,10 +1740,8 @@ uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; } grpc_compression_algorithm grpc_call_compression_for_level( grpc_call *call, grpc_compression_level level) { - gpr_mu_lock(&call->mu); grpc_compression_algorithm algo = compression_algorithm_for_level_locked(call, level); - gpr_mu_unlock(&call->mu); return algo; } diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c index d6acd392c1..2b700b2f67 100644 --- a/src/core/lib/surface/channel.c +++ b/src/core/lib/surface/channel.c @@ -68,6 +68,8 @@ struct grpc_channel { grpc_compression_options compression_options; grpc_mdelem default_authority; + gpr_atm call_size_estimate; + gpr_mu registered_call_mu; registered_call *registered_calls; @@ -115,6 +117,10 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target, gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = NULL; + gpr_atm_no_barrier_store( + &channel->call_size_estimate, + (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size); + grpc_compression_options_init(&channel->compression_options); for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { @@ -177,6 +183,32 @@ done: return channel; } +size_t grpc_channel_get_call_size_estimate(grpc_channel *channel) { +#define ROUND_UP_SIZE 256 + return ((size_t)gpr_atm_no_barrier_load(&channel->call_size_estimate) + + ROUND_UP_SIZE) & + ~(size_t)(ROUND_UP_SIZE - 1); +} + +void grpc_channel_update_call_size_estimate(grpc_channel *channel, + size_t size) { + size_t cur = (size_t)gpr_atm_no_barrier_load(&channel->call_size_estimate); + if (cur < size) { + /* size grew: update estimate */ + gpr_atm_no_barrier_cas(&channel->call_size_estimate, (gpr_atm)cur, + (gpr_atm)size); + /* if we lose: never mind, something else will likely update soon enough */ + } else if (cur == size) { + /* no change: holding pattern */ + } else if (cur > 0) { + /* size shrank: decrease estimate */ + gpr_atm_no_barrier_cas( + &channel->call_size_estimate, (gpr_atm)cur, + (gpr_atm)(GPR_MIN(cur - 1, (255 * cur + size) / 256))); + /* if we lose: never mind, something else will likely update soon enough */ + } +} + char *grpc_channel_get_target(grpc_channel *channel) { GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel)); return gpr_strdup(channel->target); diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h index 3a441d7add..c4aebd8b9b 100644 --- a/src/core/lib/surface/channel.h +++ b/src/core/lib/surface/channel.h @@ -66,6 +66,9 @@ grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx, grpc_channel *channel, int status_code); +size_t grpc_channel_get_call_size_estimate(grpc_channel *channel); +void grpc_channel_update_call_size_estimate(grpc_channel *channel, size_t size); + #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_channel_internal_ref(grpc_channel *channel, const char *reason); void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel, diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c index 49bc4c114b..9ddb88bd11 100644 --- a/src/core/lib/surface/lame_client.c +++ b/src/core/lib/surface/lame_client.c @@ -130,8 +130,8 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *and_free_memory) { - gpr_free(and_free_memory); + grpc_closure *then_schedule_closure) { + grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); } static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 7ebe130751..acc8b7016a 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -898,7 +898,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *ignored) { + grpc_closure *ignored) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; diff --git a/src/core/lib/surface/version.c b/src/core/lib/surface/version.c index 1143a9e044..ba80bd801e 100644 --- a/src/core/lib/surface/version.c +++ b/src/core/lib/surface/version.c @@ -38,4 +38,4 @@ const char *grpc_version_string(void) { return "3.0.0-dev"; } -const char *grpc_g_stands_for(void) { return "green"; } +const char *grpc_g_stands_for(void) { return "gentle"; } diff --git a/src/core/lib/transport/error_utils.c b/src/core/lib/transport/error_utils.c index da77828d9c..ef55e561fb 100644 --- a/src/core/lib/transport/error_utils.c +++ b/src/core/lib/transport/error_utils.c @@ -44,12 +44,12 @@ static grpc_error *recursively_find_error_with_field(grpc_error *error, } if (grpc_error_is_special(error)) return NULL; // Otherwise, search through its children. - intptr_t key = 0; - while (true) { - grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++); - if (child_error == NULL) break; - grpc_error *result = recursively_find_error_with_field(child_error, which); - if (result != NULL) return result; + uint8_t slot = error->first_err; + while (slot != UINT8_MAX) { + grpc_linked_error *lerr = (grpc_linked_error *)(error->arena + slot); + grpc_error *result = recursively_find_error_with_field(lerr->err, which); + if (result) return result; + slot = lerr->next; } return NULL; } @@ -112,13 +112,13 @@ bool grpc_error_has_clear_grpc_status(grpc_error *error) { if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { return true; } - intptr_t key = 0; - while (true) { - grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++); - if (child_error == NULL) break; - if (grpc_error_has_clear_grpc_status(child_error)) { + uint8_t slot = error->first_err; + while (slot != UINT8_MAX) { + grpc_linked_error *lerr = (grpc_linked_error *)(error->arena + slot); + if (grpc_error_has_clear_grpc_status(lerr->err)) { return true; } + slot = lerr->next; } return false; } diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 165950e288..d56cb31ee0 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -162,9 +162,9 @@ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_stream_refcount *refcount, - const void *server_data) { + const void *server_data, gpr_arena *arena) { return transport->vtable->init_stream(exec_ctx, transport, stream, refcount, - server_data); + server_data, arena); } void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx, @@ -197,9 +197,10 @@ void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport, void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, - grpc_stream *stream, void *and_free_memory) { + grpc_stream *stream, + grpc_closure *then_schedule_closure) { transport->vtable->destroy_stream(exec_ctx, transport, stream, - and_free_memory); + then_schedule_closure); } char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx, @@ -254,8 +255,9 @@ typedef struct { static void destroy_made_transport_stream_op(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { made_transport_stream_op *op = arg; - grpc_closure_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error)); + grpc_closure *c = op->inner_on_complete; gpr_free(op); + grpc_closure_run(exec_ctx, c, GRPC_ERROR_REF(error)); } grpc_transport_stream_op *grpc_make_transport_stream_op( diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index cc1c277b35..950b18aeda 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -41,6 +41,7 @@ #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/support/arena.h" #include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/metadata_batch.h" @@ -229,7 +230,7 @@ size_t grpc_transport_stream_size(grpc_transport *transport); int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_stream_refcount *refcount, - const void *server_data); + const void *server_data, gpr_arena *arena); void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_polling_entity *pollent); @@ -246,7 +247,8 @@ void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport, caller, but any child memory must be cleaned up) */ void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, - grpc_stream *stream, void *and_free_memory); + grpc_stream *stream, + grpc_closure *then_schedule_closure); void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op, diff --git a/src/core/lib/transport/transport_impl.h b/src/core/lib/transport/transport_impl.h index 8553148c35..6f688bf8d2 100644 --- a/src/core/lib/transport/transport_impl.h +++ b/src/core/lib/transport/transport_impl.h @@ -47,7 +47,7 @@ typedef struct grpc_transport_vtable { /* implementation of grpc_transport_init_stream */ int (*init_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self, grpc_stream *stream, grpc_stream_refcount *refcount, - const void *server_data); + const void *server_data, gpr_arena *arena); /* implementation of grpc_transport_set_pollset */ void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_transport *self, @@ -67,7 +67,8 @@ typedef struct grpc_transport_vtable { /* implementation of grpc_transport_destroy_stream */ void (*destroy_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self, - grpc_stream *stream, void *and_free_memory); + grpc_stream *stream, + grpc_closure *then_schedule_closure); /* implementation of grpc_transport_destroy */ void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_transport *self); diff --git a/src/cpp/common/channel_arguments.cc b/src/cpp/common/channel_arguments.cc index 65f3277499..eddcacc332 100644 --- a/src/cpp/common/channel_arguments.cc +++ b/src/cpp/common/channel_arguments.cc @@ -81,6 +81,16 @@ ChannelArguments::ChannelArguments(const ChannelArguments& other) } } +ChannelArguments::~ChannelArguments() { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + for (auto it = args_.begin(); it != args_.end(); ++it) { + if (it->type == GRPC_ARG_POINTER) { + it->value.pointer.vtable->destroy(&exec_ctx, it->value.pointer.p); + } + } + grpc_exec_ctx_finish(&exec_ctx); +} + void ChannelArguments::Swap(ChannelArguments& other) { args_.swap(other.args_); strings_.swap(other.strings_); @@ -101,8 +111,10 @@ void ChannelArguments::SetSocketMutator(grpc_socket_mutator* mutator) { for (auto it = args_.begin(); it != args_.end(); ++it) { if (it->type == mutator_arg.type && grpc::string(it->key) == grpc::string(mutator_arg.key)) { + GPR_ASSERT(!replaced); it->value.pointer.vtable->destroy(&exec_ctx, it->value.pointer.p); it->value.pointer = mutator_arg.value.pointer; + replaced = true; } } grpc_exec_ctx_finish(&exec_ctx); @@ -185,7 +197,7 @@ void ChannelArguments::SetPointerWithVtable( arg.type = GRPC_ARG_POINTER; strings_.push_back(key); arg.key = const_cast<char*>(strings_.back().c_str()); - arg.value.pointer.p = value; + arg.value.pointer.p = vtable->copy(value); arg.value.pointer.vtable = vtable; args_.push_back(arg); } diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h index 79c4bab985..494d5d64d7 100644 --- a/src/cpp/common/channel_filter.h +++ b/src/cpp/common/channel_filter.h @@ -318,7 +318,8 @@ class ChannelFilter final { static void DestroyCallElement(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, - void *and_free_memory) { + grpc_closure *then_call_closure) { + GPR_ASSERT(then_call_closure == NULL); reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType(); } diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 039c530cdc..f5a0e4131d 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -37,5 +37,5 @@ #include <grpc++/grpc++.h> namespace grpc { -grpc::string Version() { return "1.2.0-dev"; } +grpc::string Version() { return "1.3.0-dev"; } } diff --git a/src/cpp/server/channel_argument_option.cc b/src/cpp/server/channel_argument_option.cc new file mode 100644 index 0000000000..723f968ff8 --- /dev/null +++ b/src/cpp/server/channel_argument_option.cc @@ -0,0 +1,78 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc++/impl/channel_argument_option.h> + +namespace grpc { + +std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption( + const grpc::string &name, const grpc::string &value) { + class StringOption final : public ServerBuilderOption { + public: + StringOption(const grpc::string &name, const grpc::string &value) + : name_(name), value_(value) {} + + virtual void UpdateArguments(ChannelArguments *args) override { + args->SetString(name_, value_); + } + virtual void UpdatePlugins( + std::vector<std::unique_ptr<ServerBuilderPlugin>> *plugins) override {} + + private: + const grpc::string name_; + const grpc::string value_; + }; + return std::unique_ptr<ServerBuilderOption>(new StringOption(name, value)); +} + +std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption( + const grpc::string &name, int value) { + class IntOption final : public ServerBuilderOption { + public: + IntOption(const grpc::string &name, int value) + : name_(name), value_(value) {} + + virtual void UpdateArguments(ChannelArguments *args) override { + args->SetInt(name_, value_); + } + virtual void UpdatePlugins( + std::vector<std::unique_ptr<ServerBuilderPlugin>> *plugins) override {} + + private: + const grpc::string name_; + const int value_; + }; + return std::unique_ptr<ServerBuilderOption>(new IntOption(name, value)); +} + +} // namespace grpc diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 00a90bb184..4eb4b5a1b2 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -323,9 +323,14 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() { } } + bool added_port = false; for (auto port = ports_.begin(); port != ports_.end(); port++) { int r = server->AddListeningPort(port->addr, port->creds.get()); - if (!r) return nullptr; + if (!r) { + if (added_port) server->Shutdown(); + return nullptr; + } + added_port = true; if (port->selected_port != nullptr) { *port->selected_port = r; } @@ -333,6 +338,7 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() { auto cqs_data = cqs_.empty() ? nullptr : &cqs_[0]; if (!server->Start(cqs_data, cqs_.size())) { + if (added_port) server->Shutdown(); return nullptr; } diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 50c4cafa7a..b11ea725e1 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -545,7 +545,7 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { void Server::ShutdownInternal(gpr_timespec deadline) { std::unique_lock<std::mutex> lock(mu_); - if (started_ && !shutdown_) { + if (!shutdown_) { shutdown_ = true; /// The completion queue to use for server shutdown completion notification diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json index 170149ace5..370bf11b2d 100644 --- a/src/csharp/Grpc.Auth/project.json +++ b/src/csharp/Grpc.Auth/project.json @@ -1,5 +1,5 @@ { - "version": "1.2.0-dev", + "version": "1.3.0-dev", "title": "gRPC C# Auth", "authors": [ "Google Inc." ], "copyright": "Copyright 2015, Google Inc.", @@ -21,7 +21,7 @@ } }, "dependencies": { - "Grpc.Core": "1.2.0-dev", + "Grpc.Core": "1.3.0-dev", "Google.Apis.Auth": "1.21.0" }, "frameworks": { diff --git a/src/csharp/Grpc.Core.Testing/project.json b/src/csharp/Grpc.Core.Testing/project.json index 02be957812..38d5fab50e 100644 --- a/src/csharp/Grpc.Core.Testing/project.json +++ b/src/csharp/Grpc.Core.Testing/project.json @@ -1,5 +1,5 @@ { - "version": "1.2.0-dev", + "version": "1.3.0-dev", "title": "gRPC C# Core Testing", "authors": [ "Google Inc." ], "copyright": "Copyright 2017, Google Inc.", @@ -21,7 +21,7 @@ } }, "dependencies": { - "Grpc.Core": "1.2.0-dev" + "Grpc.Core": "1.3.0-dev" }, "frameworks": { "net45": { diff --git a/src/csharp/Grpc.Core.Tests/TestResult.xml b/src/csharp/Grpc.Core.Tests/TestResult.xml deleted file mode 100644 index 13da80739c..0000000000 --- a/src/csharp/Grpc.Core.Tests/TestResult.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<!--This file represents the results of running a test suite--> -<test-results name="/usr/local/google/home/jtattermusch/github/grpc/src/csharp/GrpcCoreTests/bin/Debug/GrpcCoreTests.dll" total="3" errors="0" failures="0" not-run="0" inconclusive="0" ignored="0" skipped="0" invalid="0" date="2015-01-29" time="19:40:47"> - <environment nunit-version="2.6.0.0" clr-version="4.0.30319.17020" os-version="Unix 3.13.0.43" platform="Unix" cwd="/usr/local/google/home/jtattermusch/github/grpc/src/csharp/GrpcCoreTests" machine-name="jtattermusch.mtv.corp.google.com" user="jtattermusch" user-domain="jtattermusch.mtv.corp.google.com" /> - <culture-info current-culture="en-US" current-uiculture="en-US" /> - <test-suite type="Assembly" name="/usr/local/google/home/jtattermusch/github/grpc/src/csharp/GrpcCoreTests/bin/Debug/GrpcCoreTests.dll" executed="True" result="Success" success="True" time="0.172" asserts="0"> - <results> - <test-suite type="Namespace" name="Google" executed="True" result="Success" success="True" time="0.166" asserts="0"> - <results> - <test-suite type="Namespace" name="GRPC" executed="True" result="Success" success="True" time="0.166" asserts="0"> - <results> - <test-suite type="Namespace" name="Core" executed="True" result="Success" success="True" time="0.166" asserts="0"> - <results> - <test-suite type="Namespace" name="Tests" executed="True" result="Success" success="True" time="0.166" asserts="0"> - <results> - <test-suite type="TestFixture" name="CallsTest" executed="True" result="Success" success="True" time="0.009" asserts="0"> - <results> - <test-case name="Grpc.Core.Tests.CallsTest.Test1" executed="True" result="Success" success="True" time="0.004" asserts="0" /> - </results> - </test-suite> - <test-suite type="TestFixture" name="ClientServerTest" executed="True" result="Success" success="True" time="0.149" asserts="0"> - <results> - <test-case name="Grpc.Core.Tests.ClientServerTest.EmptyCall" executed="True" result="Success" success="True" time="0.111" asserts="0" /> - </results> - </test-suite> - <test-suite type="TestFixture" name="ServerTest" executed="True" result="Success" success="True" time="0.001" asserts="0"> - <results> - <test-case name="Grpc.Core.Tests.ServerTest.StartAndShutdownServer" executed="True" result="Success" success="True" time="0.001" asserts="0" /> - </results> - </test-suite> - </results> - </test-suite> - </results> - </test-suite> - </results> - </test-suite> - </results> - </test-suite> - </results> - </test-suite> -</test-results>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index f01a024db4..6012d904b6 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 = "1.2.0.0"; + public const string CurrentAssemblyFileVersion = "1.3.0.0"; /// <summary> /// Current version of gRPC C# /// </summary> - public const string CurrentVersion = "1.2.0-dev"; + public const string CurrentVersion = "1.3.0-dev"; } } diff --git a/src/csharp/Grpc.Core/project.json b/src/csharp/Grpc.Core/project.json index 0e37ec8927..a1306baa87 100644 --- a/src/csharp/Grpc.Core/project.json +++ b/src/csharp/Grpc.Core/project.json @@ -1,5 +1,5 @@ { - "version": "1.2.0-dev", + "version": "1.3.0-dev", "title": "gRPC C# Core", "authors": [ "Google Inc." ], "copyright": "Copyright 2015, Google Inc.", diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json index 9e9d245cae..e93d0bf81b 100644 --- a/src/csharp/Grpc.HealthCheck/project.json +++ b/src/csharp/Grpc.HealthCheck/project.json @@ -1,5 +1,5 @@ { - "version": "1.2.0-dev", + "version": "1.3.0-dev", "title": "gRPC C# Healthchecking", "authors": [ "Google Inc." ], "copyright": "Copyright 2015, Google Inc.", @@ -21,7 +21,7 @@ } }, "dependencies": { - "Grpc.Core": "1.2.0-dev", + "Grpc.Core": "1.3.0-dev", "Google.Protobuf": "3.2.0" }, "frameworks": { diff --git a/src/csharp/Grpc.Reflection/project.json b/src/csharp/Grpc.Reflection/project.json index 8bfe722f78..014c78e489 100644 --- a/src/csharp/Grpc.Reflection/project.json +++ b/src/csharp/Grpc.Reflection/project.json @@ -1,5 +1,5 @@ { - "version": "1.2.0-dev", + "version": "1.3.0-dev", "title": "gRPC C# Reflection", "authors": [ "Google Inc." ], "copyright": "Copyright 2016, Google Inc.", @@ -21,7 +21,7 @@ } }, "dependencies": { - "Grpc.Core": "1.2.0-dev", + "Grpc.Core": "1.3.0-dev", "Google.Protobuf": "3.2.0" }, "frameworks": { diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index b99fdcbdfd..4fec2c71cf 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -28,7 +28,7 @@ @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Current package versions -set VERSION=1.2.0-dev +set VERSION=1.3.0-dev set PROTOBUF_VERSION=3.0.0 @rem Adjust the location of nuget.exe diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index 442e3acad2..f51b42bc8c 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -66,7 +66,7 @@ dotnet pack --configuration Release Grpc.Auth/project.json --output ../../artifa dotnet pack --configuration Release Grpc.HealthCheck/project.json --output ../../artifacts dotnet pack --configuration Release Grpc.Reflection/project.json --output ../../artifacts -nuget pack Grpc.nuspec -Version "1.2.0-dev" -OutputDirectory ../../artifacts -nuget pack Grpc.Tools.nuspec -Version "1.2.0-dev" -OutputDirectory ../../artifacts +nuget pack Grpc.nuspec -Version "1.3.0-dev" -OutputDirectory ../../artifacts +nuget pack Grpc.Tools.nuspec -Version "1.3.0-dev" -OutputDirectory ../../artifacts (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) diff --git a/src/csharp/global.json b/src/csharp/global.json new file mode 100644 index 0000000000..32ff399ef9 --- /dev/null +++ b/src/csharp/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "1.0.0-preview2-003121" + } +}
\ No newline at end of file diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json index 8376339deb..e218f5a406 100644 --- a/src/node/health_check/package.json +++ b/src/node/health_check/package.json @@ -1,6 +1,6 @@ { "name": "grpc-health-check", - "version": "1.2.0-dev", + "version": "1.3.0-dev", "author": "Google Inc.", "description": "Health check service for use with gRPC", "repository": { @@ -15,7 +15,7 @@ } ], "dependencies": { - "grpc": "^1.2.0-dev", + "grpc": "^1.3.0-dev", "lodash": "^3.9.3", "google-protobuf": "^3.0.0" }, diff --git a/src/node/src/server.js b/src/node/src/server.js index 8a7eff507d..a5a0ea2642 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -728,7 +728,7 @@ var defaultHandler = { * method implementation for the provided service. */ Server.prototype.addService = function(service, implementation) { - if (!_.isObjectLike(service) || !_.isObjectLike(implementation)) { + if (!_.isObject(service) || !_.isObject(implementation)) { throw new Error('addService requires two objects as arguments'); } if (_.keys(service).length === 0) { diff --git a/src/node/tools/package.json b/src/node/tools/package.json index 53dd53f539..3096c6e42a 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "1.2.0-dev", + "version": "1.3.0-dev", "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 index 1a3b775c60..ab8f82a39e 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # 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.2.0-dev' + v = '1.3.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index e569faa25b..09155ee4d4 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -38,4 +38,4 @@ // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.2.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.3.0-dev" diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 5584246ad9..d964f53e8e 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -90,6 +90,9 @@ return nil; } +// This number indicates how many bytes of overhead does Protocol Buffers encoding add onto the +// message. The number varies as different message.proto is used on different servers. The actual +// number for each interop server is overridden in corresponding derived test classes. - (int32_t)encodingOverhead { return 0; } @@ -169,8 +172,6 @@ [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -#ifndef GRPC_COMPILE_WITH_CRONET -// TODO (mxyan): Fix this test - (void)testResponsesOverMaxSizeFailWithActionableMessage { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"]; @@ -191,7 +192,6 @@ [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -#endif - (void)testResponsesOver4MBAreAcceptedIfOptedIn { XCTAssertNotNil(self.class.host); @@ -327,8 +327,6 @@ [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -#ifndef GRPC_COMPILE_WITH_CRONET -// TODO(makdharma@): Fix this test - (void)testEmptyStreamRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; @@ -342,7 +340,6 @@ }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -#endif - (void)testCancelAfterBeginRPC { XCTAssertNotNil(self.class.host); diff --git a/src/objective-c/tests/InteropTestsLocalCleartext.m b/src/objective-c/tests/InteropTestsLocalCleartext.m index b41210f50f..4987660808 100644 --- a/src/objective-c/tests/InteropTestsLocalCleartext.m +++ b/src/objective-c/tests/InteropTestsLocalCleartext.m @@ -37,6 +37,10 @@ static NSString * const kLocalCleartextHost = @"localhost:5050"; +// The Protocol Buffers encoding overhead of local interop server. Acquired +// by experiment. Adjust this when server's proto file changes. +static int32_t kLocalInteropServerOverhead = 10; + /** Tests in InteropTests.m, sending the RPCs to a local cleartext server. */ @interface InteropTestsLocalCleartext : InteropTests @end @@ -48,7 +52,7 @@ static NSString * const kLocalCleartextHost = @"localhost:5050"; } - (int32_t)encodingOverhead { - return 10; // bytes + return kLocalInteropServerOverhead; // bytes } - (void)setUp { diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m index 1479c5896c..934d500abc 100644 --- a/src/objective-c/tests/InteropTestsLocalSSL.m +++ b/src/objective-c/tests/InteropTestsLocalSSL.m @@ -37,6 +37,10 @@ static NSString * const kLocalSSLHost = @"localhost:5051"; +// The Protocol Buffers encoding overhead of local interop server. Acquired +// by experiment. Adjust this when server's proto file changes. +static int32_t kLocalInteropServerOverhead = 10; + /** Tests in InteropTests.m, sending the RPCs to a local SSL server. */ @interface InteropTestsLocalSSL : InteropTests @end @@ -48,7 +52,7 @@ static NSString * const kLocalSSLHost = @"localhost:5051"; } - (int32_t)encodingOverhead { - return 10; // bytes + return kLocalInteropServerOverhead; // bytes } - (void)setUp { diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m index 70f84753bb..9fb30aa43d 100644 --- a/src/objective-c/tests/InteropTestsRemote.m +++ b/src/objective-c/tests/InteropTestsRemote.m @@ -37,6 +37,10 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; +// The Protocol Buffers encoding overhead of remote interop server. Acquired +// by experiment. Adjust this when server's proto file changes. +static int32_t kRemoteInteropServerOverhead = 12; + /** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */ @interface InteropTestsRemote : InteropTests @end @@ -48,7 +52,7 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; } - (int32_t)encodingOverhead { - return 12; // bytes + return kRemoteInteropServerOverhead; // bytes } @end diff --git a/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m index fab8ad8d25..005bac0a0d 100644 --- a/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m +++ b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m @@ -37,6 +37,10 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; +// The Protocol Buffers encoding overhead of remote interop server. Acquired +// by experiment. Adjust this when server's proto file changes. +static int32_t kRemoteInteropServerOverhead = 12; + /** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */ @interface InteropTestsRemoteWithCronet : InteropTests @end @@ -47,4 +51,8 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; return kRemoteSSLHost; } +- (int32_t)encodingOverhead { + return kRemoteInteropServerOverhead; // bytes +} + @end diff --git a/src/php/composer.json b/src/php/composer.json index 491e34795a..2b140077cc 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "BSD-3-Clause", - "version": "1.2.0", + "version": "1.3.0", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.1.0" diff --git a/src/php/tests/qps/client.php b/src/php/tests/qps/client.php new file mode 100644 index 0000000000..d9ca35ba43 --- /dev/null +++ b/src/php/tests/qps/client.php @@ -0,0 +1,166 @@ +<?php +/* + * + * Copyright 2017, 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. + * + */ + +/* + * PHP client for QPS testing works as follows: + * 1. Gets initiated by a call from a proxy that implements the worker service. The + * argument to this client is the proxy connection information + * 2. Initiate an RPC to the proxy to get ClientConfig + * 3. Initiate a client-side telemetry RPC to the proxy + * 4. Parse the client config, which includes server target information and then start + * a unary or streaming test as appropriate. + * 5. After each completed RPC, send its timing to the proxy. The proxy does all histogramming + * 6. Proxy will respond on the timing channel when it's time to complete. Our + * next timing write will fail and we know that it's time to stop + * The above complex dance is since threading and async are not idiomatic and we + * shouldn't ever be waiting to read a mark + * + * This test only supports a single channel since threading/async is not idiomatic + * This test supports unary or streaming ping-pongs, as well as open-loop + * + */ + +require dirname(__FILE__).'/vendor/autoload.php'; + +/** + * Assertion function that always exits with an error code if the assertion is + * falsy. + * + * @param $value Assertion value. Should be true. + * @param $error_message Message to display if the assertion is false + */ +function hardAssert($value, $error_message) +{ + if (!$value) { + echo $error_message."\n"; + exit(1); + } +} + +function hardAssertIfStatusOk($status) +{ + if ($status->code !== Grpc\STATUS_OK) { + echo "Call did not complete successfully. Status object:\n"; + var_dump($status); + exit(1); + } +} + +/* Start the actual client */ + +function qps_client_main($proxy_address) { + echo "Initiating php client\n"; + + $proxystubopts = []; + $proxystubopts['credentials'] = Grpc\ChannelCredentials::createInsecure(); + $proxystub = new Grpc\Testing\ProxyClientServiceClient($proxy_address, $proxystubopts); + list($config, $status) = $proxystub->GetConfig(new Grpc\Testing\Void())->wait(); + hardAssertIfStatusOk($status); + hardAssert($config->getClientChannels() == 1, "Only 1 channel supported"); + hardAssert($config->getOutstandingRpcsPerChannel() == 1, "Only 1 outstanding RPC supported"); + + echo "Got configuration from proxy, target is " . $config->getServerTargets()[0] . "\n"; + + $stubopts = []; + if ($config->getSecurityParams()) { + if ($config->getSecurityParams()->getUseTestCa()) { + $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); + } else { + $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl(null); + } + $override = $config->getSecurityParams()->getServerHostOverride(); + if ($override) { + $stubopts['grpc.ssl_target_name_override'] = $override; + $stubopts['grpc.default_authority'] = $override; + } + } else { + $stubopts['credentials'] = Grpc\ChannelCredentials::createInsecure(); + } + echo "Initiating php benchmarking client\n"; + + $stub = new Grpc\Testing\BenchmarkServiceClient( + $config->getServerTargets()[0], $stubopts); + $req = new Grpc\Testing\SimpleRequest(); + + $req->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); + $req->setResponseSize($config->getPayloadConfig()->getSimpleParams()->getRespSize()); + $payload = new Grpc\Testing\Payload(); + $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE); + $payload->setBody(str_repeat("\0", $config->getPayloadConfig()->getSimpleParams()->getReqSize())); + $req->setPayload($payload); + + /* TODO(stanley-cheung): Enable the following by removing the 0&& once protobuf + * properly supports oneof in PHP */ + if (0 && $config->getLoadParams()->getLoad() == "poisson") { + $poisson = true; + $lamrecip = 1.0/($config->getLoadParams()->getPoisson()->getOfferedLoad()); + $issue = microtime(true) + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); + } else { + $poisson = false; + } + $metric = new Grpc\Testing\ProxyStat; + $telemetry = $proxystub->ReportTime(); + if ($config->getRpcType() == Grpc\Testing\RpcType::UNARY) { + while (1) { + if ($poisson) { + time_sleep_until($issue); + $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); + } + $startreq = microtime(true); + list($resp,$status) = $stub->UnaryCall($req)->wait(); + hardAssertIfStatusOk($status); + $metric->setLatency(microtime(true)-$startreq); + $telemetry->write($metric); + } + } else { + $stream = $stub->StreamingCall(); + while (1) { + if ($poisson) { + time_sleep_until($issue); + $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); + } + $startreq = microtime(true); + $stream->write($req); + $resp = $stream->read(); + $metric->setLatency(microtime(true)-$startreq); + $telemetry->write($metric); + } + } +} + +ini_set('display_startup_errors', 1); +ini_set('display_errors', 1); +error_reporting(-1); +qps_client_main($argv[1]); diff --git a/src/php/tests/qps/composer.json b/src/php/tests/qps/composer.json new file mode 100644 index 0000000000..0fc87098f5 --- /dev/null +++ b/src/php/tests/qps/composer.json @@ -0,0 +1,11 @@ +{ + "minimum-stability": "dev", + "require": { + "grpc/grpc": "dev-master" + }, + "autoload": { + "psr-4": { + "": "generated_code/" + } + } +} diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php new file mode 100644 index 0000000000..efca18a0cb --- /dev/null +++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php @@ -0,0 +1,127 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace GPBMetadata\Src\Proto\Grpc\Testing; + +class Control +{ + public static $is_initialized = false; + + public static function initOnce() { + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + + if (static::$is_initialized == true) { + return; + } + \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); + \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); + $pool->internalAddGeneratedFile(hex2bin( + "0add170a247372632f70726f746f2f677270632f74657374696e672f636f" . + "6e74726f6c2e70726f746f120c677270632e74657374696e671a25737263" . + "2f70726f746f2f677270632f74657374696e672f7061796c6f6164732e70" . + "726f746f1a227372632f70726f746f2f677270632f74657374696e672f73" . + "746174732e70726f746f22250a0d506f6973736f6e506172616d7312140a" . + "0c6f6666657265645f6c6f616418012001280122120a10436c6f7365644c" . + "6f6f70506172616d73227b0a0a4c6f6164506172616d7312350a0b636c6f" . + "7365645f6c6f6f7018012001280b321e2e677270632e74657374696e672e" . + "436c6f7365644c6f6f70506172616d734800122e0a07706f6973736f6e18" . + "022001280b321b2e677270632e74657374696e672e506f6973736f6e5061" . + "72616d73480042060a046c6f616422430a0e536563757269747950617261" . + "6d7312130a0b7573655f746573745f6361180120012808121c0a14736572" . + "7665725f686f73745f6f76657272696465180220012809224d0a0a436861" . + "6e6e656c417267120c0a046e616d6518012001280912130a097374725f76" . + "616c7565180220012809480012130a09696e745f76616c75651803200128" . + "05480042070a0576616c756522a0040a0c436c69656e74436f6e66696712" . + "160a0e7365727665725f74617267657473180120032809122d0a0b636c69" . + "656e745f7479706518022001280e32182e677270632e74657374696e672e" . + "436c69656e745479706512350a0f73656375726974795f706172616d7318" . + "032001280b321c2e677270632e74657374696e672e536563757269747950" . + "6172616d7312240a1c6f75747374616e64696e675f727063735f7065725f" . + "6368616e6e656c18042001280512170a0f636c69656e745f6368616e6e65" . + "6c73180520012805121c0a146173796e635f636c69656e745f7468726561" . + "647318072001280512270a087270635f7479706518082001280e32152e67" . + "7270632e74657374696e672e52706354797065122d0a0b6c6f61645f7061" . + "72616d73180a2001280b32182e677270632e74657374696e672e4c6f6164" . + "506172616d7312330a0e7061796c6f61645f636f6e666967180b2001280b" . + "321b2e677270632e74657374696e672e5061796c6f6164436f6e66696712" . + "370a10686973746f6772616d5f706172616d73180c2001280b321d2e6772" . + "70632e74657374696e672e486973746f6772616d506172616d7312110a09" . + "636f72655f6c697374180d2003280512120a0a636f72655f6c696d697418" . + "0e2001280512180a106f746865725f636c69656e745f617069180f200128" . + "09122e0a0c6368616e6e656c5f6172677318102003280b32182e67727063" . + "2e74657374696e672e4368616e6e656c41726722380a0c436c69656e7453" . + "746174757312280a05737461747318012001280b32192e677270632e7465" . + "7374696e672e436c69656e74537461747322150a044d61726b120d0a0572" . + "6573657418012001280822680a0a436c69656e7441726773122b0a057365" . + "74757018012001280b321a2e677270632e74657374696e672e436c69656e" . + "74436f6e666967480012220a046d61726b18022001280b32122e67727063" . + "2e74657374696e672e4d61726b480042090a076172677479706522b4020a" . + "0c536572766572436f6e666967122d0a0b7365727665725f747970651801" . + "2001280e32182e677270632e74657374696e672e53657276657254797065" . + "12350a0f73656375726974795f706172616d7318022001280b321c2e6772" . + "70632e74657374696e672e5365637572697479506172616d73120c0a0470" . + "6f7274180420012805121c0a146173796e635f7365727665725f74687265" . + "61647318072001280512120a0a636f72655f6c696d697418082001280512" . + "330a0e7061796c6f61645f636f6e66696718092001280b321b2e67727063" . + "2e74657374696e672e5061796c6f6164436f6e66696712110a09636f7265" . + "5f6c697374180a2003280512180a106f746865725f7365727665725f6170" . + "69180b20012809121c0a137265736f757263655f71756f74615f73697a65" . + "18e9072001280522680a0a53657276657241726773122b0a057365747570" . + "18012001280b321a2e677270632e74657374696e672e536572766572436f" . + "6e666967480012220a046d61726b18022001280b32122e677270632e7465" . + "7374696e672e4d61726b480042090a076172677479706522550a0c536572" . + "76657253746174757312280a05737461747318012001280b32192e677270" . + "632e74657374696e672e5365727665725374617473120c0a04706f727418" . + "0220012805120d0a05636f726573180320012805220d0a0b436f72655265" . + "7175657374221d0a0c436f7265526573706f6e7365120d0a05636f726573" . + "18012001280522060a04566f696422fd010a085363656e6172696f120c0a" . + "046e616d6518012001280912310a0d636c69656e745f636f6e6669671802" . + "2001280b321a2e677270632e74657374696e672e436c69656e74436f6e66" . + "696712130a0b6e756d5f636c69656e747318032001280512310a0d736572" . + "7665725f636f6e66696718042001280b321a2e677270632e74657374696e" . + "672e536572766572436f6e66696712130a0b6e756d5f7365727665727318" . + "052001280512160a0e7761726d75705f7365636f6e647318062001280512" . + "190a1162656e63686d61726b5f7365636f6e647318072001280512200a18" . + "737061776e5f6c6f63616c5f776f726b65725f636f756e74180820012805" . + "22360a095363656e6172696f7312290a097363656e6172696f7318012003" . + "280b32162e677270632e74657374696e672e5363656e6172696f22f8020a" . + "155363656e6172696f526573756c7453756d6d617279120b0a0371707318" . + "0120012801121b0a137170735f7065725f7365727665725f636f72651802" . + "20012801121a0a127365727665725f73797374656d5f74696d6518032001" . + "280112180a107365727665725f757365725f74696d65180420012801121a" . + "0a12636c69656e745f73797374656d5f74696d6518052001280112180a10" . + "636c69656e745f757365725f74696d6518062001280112120a0a6c617465" . + "6e63795f353018072001280112120a0a6c6174656e63795f393018082001" . + "280112120a0a6c6174656e63795f393518092001280112120a0a6c617465" . + "6e63795f3939180a2001280112130a0b6c6174656e63795f393939180b20" . + "01280112180a107365727665725f6370755f7573616765180c2001280112" . + "260a1e7375636365737366756c5f72657175657374735f7065725f736563" . + "6f6e64180d2001280112220a1a6661696c65645f72657175657374735f70" . + "65725f7365636f6e64180e200128012283030a0e5363656e6172696f5265" . + "73756c7412280a087363656e6172696f18012001280b32162e677270632e" . + "74657374696e672e5363656e6172696f122e0a096c6174656e6369657318" . + "022001280b321b2e677270632e74657374696e672e486973746f6772616d" . + "44617461122f0a0c636c69656e745f737461747318032003280b32192e67" . + "7270632e74657374696e672e436c69656e745374617473122f0a0c736572" . + "7665725f737461747318042003280b32192e677270632e74657374696e67" . + "2e536572766572537461747312140a0c7365727665725f636f7265731805" . + "2003280512340a0773756d6d61727918062001280b32232e677270632e74" . + "657374696e672e5363656e6172696f526573756c7453756d6d6172791216" . + "0a0e636c69656e745f7375636365737318072003280812160a0e73657276" . + "65725f7375636365737318082003280812390a0f726571756573745f7265" . + "73756c747318092003280b32202e677270632e74657374696e672e526571" . + "75657374526573756c74436f756e742a410a0a436c69656e745479706512" . + "0f0a0b53594e435f434c49454e54100012100a0c4153594e435f434c4945" . + "4e54100112100a0c4f544845525f434c49454e5410022a5b0a0a53657276" . + "657254797065120f0a0b53594e435f534552564552100012100a0c415359" . + "4e435f534552564552100112180a144153594e435f47454e455249435f53" . + "4552564552100212100a0c4f544845525f53455256455210032a230a0752" . + "70635479706512090a05554e4152591000120d0a0953545245414d494e47" . + "1001620670726f746f33" + )); + + static::$is_initialized = true; + } +} + diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php new file mode 100644 index 0000000000..c088002626 --- /dev/null +++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php @@ -0,0 +1,69 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace GPBMetadata\Src\Proto\Grpc\Testing; + +class Messages +{ + public static $is_initialized = false; + + public static function initOnce() { + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + + if (static::$is_initialized == true) { + return; + } + $pool->internalAddGeneratedFile(hex2bin( + "0ad50a0a257372632f70726f746f2f677270632f74657374696e672f6d65" . + "7373616765732e70726f746f120c677270632e74657374696e67221a0a09" . + "426f6f6c56616c7565120d0a0576616c756518012001280822400a075061" . + "796c6f616412270a047479706518012001280e32192e677270632e746573" . + "74696e672e5061796c6f616454797065120c0a04626f647918022001280c" . + "222b0a0a4563686f537461747573120c0a04636f6465180120012805120f" . + "0a076d65737361676518022001280922ce020a0d53696d706c6552657175" . + "65737412300a0d726573706f6e73655f7479706518012001280e32192e67" . + "7270632e74657374696e672e5061796c6f61645479706512150a0d726573" . + "706f6e73655f73697a6518022001280512260a077061796c6f6164180320" . + "01280b32152e677270632e74657374696e672e5061796c6f616412150a0d" . + "66696c6c5f757365726e616d6518042001280812180a1066696c6c5f6f61" . + "7574685f73636f706518052001280812340a13726573706f6e73655f636f" . + "6d7072657373656418062001280b32172e677270632e74657374696e672e" . + "426f6f6c56616c756512310a0f726573706f6e73655f7374617475731807" . + "2001280b32182e677270632e74657374696e672e4563686f537461747573" . + "12320a116578706563745f636f6d7072657373656418082001280b32172e" . + "677270632e74657374696e672e426f6f6c56616c7565225f0a0e53696d70" . + "6c65526573706f6e736512260a077061796c6f616418012001280b32152e" . + "677270632e74657374696e672e5061796c6f616412100a08757365726e61" . + "6d6518022001280912130a0b6f617574685f73636f706518032001280922" . + "770a1953747265616d696e67496e70757443616c6c526571756573741226" . + "0a077061796c6f616418012001280b32152e677270632e74657374696e67" . + "2e5061796c6f616412320a116578706563745f636f6d7072657373656418" . + "022001280b32172e677270632e74657374696e672e426f6f6c56616c7565" . + "223d0a1a53747265616d696e67496e70757443616c6c526573706f6e7365" . + "121f0a17616767726567617465645f7061796c6f61645f73697a65180120" . + "01280522640a12526573706f6e7365506172616d6574657273120c0a0473" . + "697a6518012001280512130a0b696e74657276616c5f7573180220012805" . + "122b0a0a636f6d7072657373656418032001280b32172e677270632e7465" . + "7374696e672e426f6f6c56616c756522e8010a1a53747265616d696e674f" . + "757470757443616c6c5265717565737412300a0d726573706f6e73655f74" . + "79706518012001280e32192e677270632e74657374696e672e5061796c6f" . + "616454797065123d0a13726573706f6e73655f706172616d657465727318" . + "022003280b32202e677270632e74657374696e672e526573706f6e736550" . + "6172616d657465727312260a077061796c6f616418032001280b32152e67" . + "7270632e74657374696e672e5061796c6f616412310a0f726573706f6e73" . + "655f73746174757318072001280b32182e677270632e74657374696e672e" . + "4563686f53746174757322450a1b53747265616d696e674f757470757443" . + "616c6c526573706f6e736512260a077061796c6f616418012001280b3215" . + "2e677270632e74657374696e672e5061796c6f616422330a0f5265636f6e" . + "6e656374506172616d7312200a186d61785f7265636f6e6e6563745f6261" . + "636b6f66665f6d7318012001280522330a0d5265636f6e6e656374496e66" . + "6f120e0a0670617373656418012001280812120a0a6261636b6f66665f6d" . + "731802200328052a1f0a0b5061796c6f61645479706512100a0c434f4d50" . + "5245535341424c451000620670726f746f33" + )); + + static::$is_initialized = true; + } +} + diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php new file mode 100644 index 0000000000..279fe00ac8 --- /dev/null +++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php @@ -0,0 +1,37 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/payloads.proto + +namespace GPBMetadata\Src\Proto\Grpc\Testing; + +class Payloads +{ + public static $is_initialized = false; + + public static function initOnce() { + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + + if (static::$is_initialized == true) { + return; + } + $pool->internalAddGeneratedFile(hex2bin( + "0a93030a257372632f70726f746f2f677270632f74657374696e672f7061" . + "796c6f6164732e70726f746f120c677270632e74657374696e6722370a10" . + "42797465427566666572506172616d7312100a087265715f73697a651801" . + "2001280512110a09726573705f73697a6518022001280522380a1153696d" . + "706c6550726f746f506172616d7312100a087265715f73697a6518012001" . + "280512110a09726573705f73697a6518022001280522140a12436f6d706c" . + "657850726f746f506172616d7322ca010a0d5061796c6f6164436f6e6669" . + "6712380a0e627974656275665f706172616d7318012001280b321e2e6772" . + "70632e74657374696e672e42797465427566666572506172616d73480012" . + "380a0d73696d706c655f706172616d7318022001280b321f2e677270632e" . + "74657374696e672e53696d706c6550726f746f506172616d734800123a0a" . + "0e636f6d706c65785f706172616d7318032001280b32202e677270632e74" . + "657374696e672e436f6d706c657850726f746f506172616d73480042090a" . + "077061796c6f6164620670726f746f33" + )); + + static::$is_initialized = true; + } +} + diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php new file mode 100644 index 0000000000..e35944e1d8 --- /dev/null +++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php @@ -0,0 +1,34 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/proxy-service.proto + +namespace GPBMetadata\Src\Proto\Grpc\Testing; + +class ProxyService +{ + public static $is_initialized = false; + + public static function initOnce() { + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + + if (static::$is_initialized == true) { + return; + } + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + $pool->internalAddGeneratedFile(hex2bin( + "0a97020a2a7372632f70726f746f2f677270632f74657374696e672f7072" . + "6f78792d736572766963652e70726f746f120c677270632e74657374696e" . + "671a247372632f70726f746f2f677270632f74657374696e672f636f6e74" . + "726f6c2e70726f746f221c0a0950726f787953746174120f0a076c617465" . + "6e6379180120012801328e010a1250726f7879436c69656e745365727669" . + "6365123b0a09476574436f6e66696712122e677270632e74657374696e67" . + "2e566f69641a1a2e677270632e74657374696e672e436c69656e74436f6e" . + "666967123b0a0a5265706f727454696d6512172e677270632e7465737469" . + "6e672e50726f7879537461741a122e677270632e74657374696e672e566f" . + "69642801620670726f746f33" + )); + + static::$is_initialized = true; + } +} + diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php new file mode 100644 index 0000000000..7a9439a5b9 --- /dev/null +++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php @@ -0,0 +1,45 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/services.proto + +namespace GPBMetadata\Src\Proto\Grpc\Testing; + +class Services +{ + public static $is_initialized = false; + + public static function initOnce() { + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + + if (static::$is_initialized == true) { + return; + } + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + $pool->internalAddGeneratedFile(hex2bin( + "0ad1040a257372632f70726f746f2f677270632f74657374696e672f7365" . + "7276696365732e70726f746f120c677270632e74657374696e671a257372" . + "632f70726f746f2f677270632f74657374696e672f6d657373616765732e" . + "70726f746f1a247372632f70726f746f2f677270632f74657374696e672f" . + "636f6e74726f6c2e70726f746f32aa010a1042656e63686d61726b536572" . + "7669636512460a09556e61727943616c6c121b2e677270632e7465737469" . + "6e672e53696d706c65526571756573741a1c2e677270632e74657374696e" . + "672e53696d706c65526573706f6e7365124e0a0d53747265616d696e6743" . + "616c6c121b2e677270632e74657374696e672e53696d706c655265717565" . + "73741a1c2e677270632e74657374696e672e53696d706c65526573706f6e" . + "7365280130013297020a0d576f726b65725365727669636512450a095275" . + "6e53657276657212182e677270632e74657374696e672e53657276657241" . + "7267731a1a2e677270632e74657374696e672e5365727665725374617475" . + "732801300112450a0952756e436c69656e7412182e677270632e74657374" . + "696e672e436c69656e74417267731a1a2e677270632e74657374696e672e" . + "436c69656e745374617475732801300112420a09436f7265436f756e7412" . + "192e677270632e74657374696e672e436f7265526571756573741a1a2e67" . + "7270632e74657374696e672e436f7265526573706f6e736512340a0a5175" . + "6974576f726b657212122e677270632e74657374696e672e566f69641a12" . + "2e677270632e74657374696e672e566f6964620670726f746f33" + )); + + static::$is_initialized = true; + } +} + diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php new file mode 100644 index 0000000000..99c0000a52 --- /dev/null +++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php @@ -0,0 +1,44 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/stats.proto + +namespace GPBMetadata\Src\Proto\Grpc\Testing; + +class Stats +{ + public static $is_initialized = false; + + public static function initOnce() { + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + + if (static::$is_initialized == true) { + return; + } + $pool->internalAddGeneratedFile(hex2bin( + "0adf040a227372632f70726f746f2f677270632f74657374696e672f7374" . + "6174732e70726f746f120c677270632e74657374696e67227a0a0b536572" . + "766572537461747312140a0c74696d655f656c6170736564180120012801" . + "12110a0974696d655f7573657218022001280112130a0b74696d655f7379" . + "7374656d18032001280112160a0e746f74616c5f6370755f74696d651804" . + "2001280412150a0d69646c655f6370755f74696d65180520012804223b0a" . + "0f486973746f6772616d506172616d7312120a0a7265736f6c7574696f6e" . + "18012001280112140a0c6d61785f706f737369626c651802200128012277" . + "0a0d486973746f6772616d44617461120e0a066275636b65741801200328" . + "0d12100a086d696e5f7365656e18022001280112100a086d61785f736565" . + "6e180320012801120b0a0373756d18042001280112160a0e73756d5f6f66" . + "5f73717561726573180520012801120d0a05636f756e7418062001280122" . + "380a1252657175657374526573756c74436f756e7412130a0b7374617475" . + "735f636f6465180120012805120d0a05636f756e7418022001280322b601" . + "0a0b436c69656e745374617473122e0a096c6174656e6369657318012001" . + "280b321b2e677270632e74657374696e672e486973746f6772616d446174" . + "6112140a0c74696d655f656c617073656418022001280112110a0974696d" . + "655f7573657218032001280112130a0b74696d655f73797374656d180420" . + "01280112390a0f726571756573745f726573756c747318052003280b3220" . + "2e677270632e74657374696e672e52657175657374526573756c74436f75" . + "6e74620670726f746f33" + )); + + static::$is_initialized = true; + } +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php new file mode 100644 index 0000000000..daf17800cd --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php @@ -0,0 +1,78 @@ +<?php +// GENERATED CODE -- DO NOT EDIT! + +// Original file comments: +// 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. +// +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +namespace Grpc\Testing { + + class BenchmarkServiceClient extends \Grpc\BaseStub { + + /** + * @param string $hostname hostname + * @param array $opts channel options + * @param Grpc\Channel $channel (optional) re-use channel object + */ + public function __construct($hostname, $opts, $channel = null) { + parent::__construct($hostname, $opts, $channel); + } + + /** + * One request followed by one response. + * The server returns the client payload as-is. + * @param \Grpc\Testing\SimpleRequest $argument input argument + * @param array $metadata metadata + * @param array $options call options + */ + public function UnaryCall(\Grpc\Testing\SimpleRequest $argument, + $metadata = [], $options = []) { + return $this->_simpleRequest('/grpc.testing.BenchmarkService/UnaryCall', + $argument, + ['\Grpc\Testing\SimpleResponse', 'decode'], + $metadata, $options); + } + + /** + * One request followed by one response. + * The server returns the client payload as-is. + * @param array $metadata metadata + * @param array $options call options + */ + public function StreamingCall($metadata = [], $options = []) { + return $this->_bidiRequest('/grpc.testing.BenchmarkService/StreamingCall', + ['\Grpc\Testing\SimpleResponse','decode'], + $metadata, $options); + } + + } + +} diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php b/src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php new file mode 100644 index 0000000000..f0497accfb --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php @@ -0,0 +1,62 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * TODO(dgq): Go back to using well-known types once + * https://github.com/grpc/grpc/issues/6980 has been fixed. + * import "google/protobuf/wrappers.proto"; + * </pre> + * + * Protobuf type <code>grpc.testing.BoolValue</code> + */ +class BoolValue extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * The bool value. + * </pre> + * + * <code>bool value = 1;</code> + */ + private $value = false; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * The bool value. + * </pre> + * + * <code>bool value = 1;</code> + */ + public function getValue() + { + return $this->value; + } + + /** + * <pre> + * The bool value. + * </pre> + * + * <code>bool value = 1;</code> + */ + public function setValue($var) + { + GPBUtil::checkBool($var); + $this->value = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php new file mode 100644 index 0000000000..0057d38748 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php @@ -0,0 +1,65 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/payloads.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ByteBufferParams</code> + */ +class ByteBufferParams extends \Google\Protobuf\Internal\Message +{ + /** + * <code>int32 req_size = 1;</code> + */ + private $req_size = 0; + /** + * <code>int32 resp_size = 2;</code> + */ + private $resp_size = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); + parent::__construct(); + } + + /** + * <code>int32 req_size = 1;</code> + */ + public function getReqSize() + { + return $this->req_size; + } + + /** + * <code>int32 req_size = 1;</code> + */ + public function setReqSize($var) + { + GPBUtil::checkInt32($var); + $this->req_size = $var; + } + + /** + * <code>int32 resp_size = 2;</code> + */ + public function getRespSize() + { + return $this->resp_size; + } + + /** + * <code>int32 resp_size = 2;</code> + */ + public function setRespSize($var) + { + GPBUtil::checkInt32($var); + $this->resp_size = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php b/src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php new file mode 100644 index 0000000000..d2fe3ae5ff --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php @@ -0,0 +1,84 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ChannelArg</code> + */ +class ChannelArg extends \Google\Protobuf\Internal\Message +{ + /** + * <code>string name = 1;</code> + */ + private $name = ''; + protected $value; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>string name = 1;</code> + */ + public function getName() + { + return $this->name; + } + + /** + * <code>string name = 1;</code> + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + } + + /** + * <code>string str_value = 2;</code> + */ + public function getStrValue() + { + return $this->readOneof(2); + } + + /** + * <code>string str_value = 2;</code> + */ + public function setStrValue($var) + { + GPBUtil::checkString($var, True); + $this->writeOneof(2, $var); + } + + /** + * <code>int32 int_value = 3;</code> + */ + public function getIntValue() + { + return $this->readOneof(3); + } + + /** + * <code>int32 int_value = 3;</code> + */ + public function setIntValue($var) + { + GPBUtil::checkInt32($var); + $this->writeOneof(3, $var); + } + + public function getValue() + { + return $this->whichOneof("value"); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php new file mode 100644 index 0000000000..c878c5a7bc --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php @@ -0,0 +1,63 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ClientArgs</code> + */ +class ClientArgs extends \Google\Protobuf\Internal\Message +{ + protected $argtype; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>.grpc.testing.ClientConfig setup = 1;</code> + */ + public function getSetup() + { + return $this->readOneof(1); + } + + /** + * <code>.grpc.testing.ClientConfig setup = 1;</code> + */ + public function setSetup(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ClientConfig::class); + $this->writeOneof(1, $var); + } + + /** + * <code>.grpc.testing.Mark mark = 2;</code> + */ + public function getMark() + { + return $this->readOneof(2); + } + + /** + * <code>.grpc.testing.Mark mark = 2;</code> + */ + public function setMark(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Mark::class); + $this->writeOneof(2, $var); + } + + public function getArgtype() + { + return $this->whichOneof("argtype"); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php new file mode 100644 index 0000000000..52d6a75fb0 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php @@ -0,0 +1,407 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ClientConfig</code> + */ +class ClientConfig extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * List of targets to connect to. At least one target needs to be specified. + * </pre> + * + * <code>repeated string server_targets = 1;</code> + */ + private $server_targets; + /** + * <code>.grpc.testing.ClientType client_type = 2;</code> + */ + private $client_type = 0; + /** + * <code>.grpc.testing.SecurityParams security_params = 3;</code> + */ + private $security_params = null; + /** + * <pre> + * How many concurrent RPCs to start for each channel. + * For synchronous client, use a separate thread for each outstanding RPC. + * </pre> + * + * <code>int32 outstanding_rpcs_per_channel = 4;</code> + */ + private $outstanding_rpcs_per_channel = 0; + /** + * <pre> + * Number of independent client channels to create. + * i-th channel will connect to server_target[i % server_targets.size()] + * </pre> + * + * <code>int32 client_channels = 5;</code> + */ + private $client_channels = 0; + /** + * <pre> + * Only for async client. Number of threads to use to start/manage RPCs. + * </pre> + * + * <code>int32 async_client_threads = 7;</code> + */ + private $async_client_threads = 0; + /** + * <code>.grpc.testing.RpcType rpc_type = 8;</code> + */ + private $rpc_type = 0; + /** + * <pre> + * The requested load for the entire client (aggregated over all the threads). + * </pre> + * + * <code>.grpc.testing.LoadParams load_params = 10;</code> + */ + private $load_params = null; + /** + * <code>.grpc.testing.PayloadConfig payload_config = 11;</code> + */ + private $payload_config = null; + /** + * <code>.grpc.testing.HistogramParams histogram_params = 12;</code> + */ + private $histogram_params = null; + /** + * <pre> + * Specify the cores we should run the client on, if desired + * </pre> + * + * <code>repeated int32 core_list = 13;</code> + */ + private $core_list; + /** + * <code>int32 core_limit = 14;</code> + */ + private $core_limit = 0; + /** + * <pre> + * If we use an OTHER_CLIENT client_type, this string gives more detail + * </pre> + * + * <code>string other_client_api = 15;</code> + */ + private $other_client_api = ''; + /** + * <code>repeated .grpc.testing.ChannelArg channel_args = 16;</code> + */ + private $channel_args; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * List of targets to connect to. At least one target needs to be specified. + * </pre> + * + * <code>repeated string server_targets = 1;</code> + */ + public function getServerTargets() + { + return $this->server_targets; + } + + /** + * <pre> + * List of targets to connect to. At least one target needs to be specified. + * </pre> + * + * <code>repeated string server_targets = 1;</code> + */ + public function setServerTargets(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); + $this->server_targets = $var; + } + + /** + * <code>.grpc.testing.ClientType client_type = 2;</code> + */ + public function getClientType() + { + return $this->client_type; + } + + /** + * <code>.grpc.testing.ClientType client_type = 2;</code> + */ + public function setClientType($var) + { + GPBUtil::checkEnum($var, \Grpc\Testing\ClientType::class); + $this->client_type = $var; + } + + /** + * <code>.grpc.testing.SecurityParams security_params = 3;</code> + */ + public function getSecurityParams() + { + return $this->security_params; + } + + /** + * <code>.grpc.testing.SecurityParams security_params = 3;</code> + */ + public function setSecurityParams(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\SecurityParams::class); + $this->security_params = $var; + } + + /** + * <pre> + * How many concurrent RPCs to start for each channel. + * For synchronous client, use a separate thread for each outstanding RPC. + * </pre> + * + * <code>int32 outstanding_rpcs_per_channel = 4;</code> + */ + public function getOutstandingRpcsPerChannel() + { + return $this->outstanding_rpcs_per_channel; + } + + /** + * <pre> + * How many concurrent RPCs to start for each channel. + * For synchronous client, use a separate thread for each outstanding RPC. + * </pre> + * + * <code>int32 outstanding_rpcs_per_channel = 4;</code> + */ + public function setOutstandingRpcsPerChannel($var) + { + GPBUtil::checkInt32($var); + $this->outstanding_rpcs_per_channel = $var; + } + + /** + * <pre> + * Number of independent client channels to create. + * i-th channel will connect to server_target[i % server_targets.size()] + * </pre> + * + * <code>int32 client_channels = 5;</code> + */ + public function getClientChannels() + { + return $this->client_channels; + } + + /** + * <pre> + * Number of independent client channels to create. + * i-th channel will connect to server_target[i % server_targets.size()] + * </pre> + * + * <code>int32 client_channels = 5;</code> + */ + public function setClientChannels($var) + { + GPBUtil::checkInt32($var); + $this->client_channels = $var; + } + + /** + * <pre> + * Only for async client. Number of threads to use to start/manage RPCs. + * </pre> + * + * <code>int32 async_client_threads = 7;</code> + */ + public function getAsyncClientThreads() + { + return $this->async_client_threads; + } + + /** + * <pre> + * Only for async client. Number of threads to use to start/manage RPCs. + * </pre> + * + * <code>int32 async_client_threads = 7;</code> + */ + public function setAsyncClientThreads($var) + { + GPBUtil::checkInt32($var); + $this->async_client_threads = $var; + } + + /** + * <code>.grpc.testing.RpcType rpc_type = 8;</code> + */ + public function getRpcType() + { + return $this->rpc_type; + } + + /** + * <code>.grpc.testing.RpcType rpc_type = 8;</code> + */ + public function setRpcType($var) + { + GPBUtil::checkEnum($var, \Grpc\Testing\RpcType::class); + $this->rpc_type = $var; + } + + /** + * <pre> + * The requested load for the entire client (aggregated over all the threads). + * </pre> + * + * <code>.grpc.testing.LoadParams load_params = 10;</code> + */ + public function getLoadParams() + { + return $this->load_params; + } + + /** + * <pre> + * The requested load for the entire client (aggregated over all the threads). + * </pre> + * + * <code>.grpc.testing.LoadParams load_params = 10;</code> + */ + public function setLoadParams(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\LoadParams::class); + $this->load_params = $var; + } + + /** + * <code>.grpc.testing.PayloadConfig payload_config = 11;</code> + */ + public function getPayloadConfig() + { + return $this->payload_config; + } + + /** + * <code>.grpc.testing.PayloadConfig payload_config = 11;</code> + */ + public function setPayloadConfig(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\PayloadConfig::class); + $this->payload_config = $var; + } + + /** + * <code>.grpc.testing.HistogramParams histogram_params = 12;</code> + */ + public function getHistogramParams() + { + return $this->histogram_params; + } + + /** + * <code>.grpc.testing.HistogramParams histogram_params = 12;</code> + */ + public function setHistogramParams(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\HistogramParams::class); + $this->histogram_params = $var; + } + + /** + * <pre> + * Specify the cores we should run the client on, if desired + * </pre> + * + * <code>repeated int32 core_list = 13;</code> + */ + public function getCoreList() + { + return $this->core_list; + } + + /** + * <pre> + * Specify the cores we should run the client on, if desired + * </pre> + * + * <code>repeated int32 core_list = 13;</code> + */ + public function setCoreList(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); + $this->core_list = $var; + } + + /** + * <code>int32 core_limit = 14;</code> + */ + public function getCoreLimit() + { + return $this->core_limit; + } + + /** + * <code>int32 core_limit = 14;</code> + */ + public function setCoreLimit($var) + { + GPBUtil::checkInt32($var); + $this->core_limit = $var; + } + + /** + * <pre> + * If we use an OTHER_CLIENT client_type, this string gives more detail + * </pre> + * + * <code>string other_client_api = 15;</code> + */ + public function getOtherClientApi() + { + return $this->other_client_api; + } + + /** + * <pre> + * If we use an OTHER_CLIENT client_type, this string gives more detail + * </pre> + * + * <code>string other_client_api = 15;</code> + */ + public function setOtherClientApi($var) + { + GPBUtil::checkString($var, True); + $this->other_client_api = $var; + } + + /** + * <code>repeated .grpc.testing.ChannelArg channel_args = 16;</code> + */ + public function getChannelArgs() + { + return $this->channel_args; + } + + /** + * <code>repeated .grpc.testing.ChannelArg channel_args = 16;</code> + */ + public function setChannelArgs(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ChannelArg::class); + $this->channel_args = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php new file mode 100644 index 0000000000..8b9a0c33a4 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php @@ -0,0 +1,164 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/stats.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ClientStats</code> + */ +class ClientStats extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Latency histogram. Data points are in nanoseconds. + * </pre> + * + * <code>.grpc.testing.HistogramData latencies = 1;</code> + */ + private $latencies = null; + /** + * <pre> + * See ServerStats for details. + * </pre> + * + * <code>double time_elapsed = 2;</code> + */ + private $time_elapsed = 0.0; + /** + * <code>double time_user = 3;</code> + */ + private $time_user = 0.0; + /** + * <code>double time_system = 4;</code> + */ + private $time_system = 0.0; + /** + * <pre> + * Number of failed requests (one row per status code seen) + * </pre> + * + * <code>repeated .grpc.testing.RequestResultCount request_results = 5;</code> + */ + private $request_results; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Latency histogram. Data points are in nanoseconds. + * </pre> + * + * <code>.grpc.testing.HistogramData latencies = 1;</code> + */ + public function getLatencies() + { + return $this->latencies; + } + + /** + * <pre> + * Latency histogram. Data points are in nanoseconds. + * </pre> + * + * <code>.grpc.testing.HistogramData latencies = 1;</code> + */ + public function setLatencies(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\HistogramData::class); + $this->latencies = $var; + } + + /** + * <pre> + * See ServerStats for details. + * </pre> + * + * <code>double time_elapsed = 2;</code> + */ + public function getTimeElapsed() + { + return $this->time_elapsed; + } + + /** + * <pre> + * See ServerStats for details. + * </pre> + * + * <code>double time_elapsed = 2;</code> + */ + public function setTimeElapsed($var) + { + GPBUtil::checkDouble($var); + $this->time_elapsed = $var; + } + + /** + * <code>double time_user = 3;</code> + */ + public function getTimeUser() + { + return $this->time_user; + } + + /** + * <code>double time_user = 3;</code> + */ + public function setTimeUser($var) + { + GPBUtil::checkDouble($var); + $this->time_user = $var; + } + + /** + * <code>double time_system = 4;</code> + */ + public function getTimeSystem() + { + return $this->time_system; + } + + /** + * <code>double time_system = 4;</code> + */ + public function setTimeSystem($var) + { + GPBUtil::checkDouble($var); + $this->time_system = $var; + } + + /** + * <pre> + * Number of failed requests (one row per status code seen) + * </pre> + * + * <code>repeated .grpc.testing.RequestResultCount request_results = 5;</code> + */ + public function getRequestResults() + { + return $this->request_results; + } + + /** + * <pre> + * Number of failed requests (one row per status code seen) + * </pre> + * + * <code>repeated .grpc.testing.RequestResultCount request_results = 5;</code> + */ + public function setRequestResults(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\RequestResultCount::class); + $this->request_results = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php new file mode 100644 index 0000000000..a59f87a962 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php @@ -0,0 +1,44 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ClientStatus</code> + */ +class ClientStatus extends \Google\Protobuf\Internal\Message +{ + /** + * <code>.grpc.testing.ClientStats stats = 1;</code> + */ + private $stats = null; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>.grpc.testing.ClientStats stats = 1;</code> + */ + public function getStats() + { + return $this->stats; + } + + /** + * <code>.grpc.testing.ClientStats stats = 1;</code> + */ + public function setStats(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ClientStats::class); + $this->stats = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php new file mode 100644 index 0000000000..4f59da992f --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php @@ -0,0 +1,34 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +/** + * Protobuf enum <code>grpc.testing.ClientType</code> + */ +class ClientType +{ + /** + * <pre> + * Many languages support a basic distinction between using + * sync or async client, and this allows the specification + * </pre> + * + * <code>SYNC_CLIENT = 0;</code> + */ + const SYNC_CLIENT = 0; + /** + * <code>ASYNC_CLIENT = 1;</code> + */ + const ASYNC_CLIENT = 1; + /** + * <pre> + * used for some language-specific variants + * </pre> + * + * <code>OTHER_CLIENT = 2;</code> + */ + const OTHER_CLIENT = 2; +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php new file mode 100644 index 0000000000..53f2948af2 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php @@ -0,0 +1,28 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Once an RPC finishes, immediately start a new one. + * No configuration parameters needed. + * </pre> + * + * Protobuf type <code>grpc.testing.ClosedLoopParams</code> + */ +class ClosedLoopParams extends \Google\Protobuf\Internal\Message +{ + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php new file mode 100644 index 0000000000..6d990f1b06 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php @@ -0,0 +1,28 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/payloads.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * TODO (vpai): Fill this in once the details of complex, representative + * protos are decided + * </pre> + * + * Protobuf type <code>grpc.testing.ComplexProtoParams</code> + */ +class ComplexProtoParams extends \Google\Protobuf\Internal\Message +{ + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); + parent::__construct(); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php new file mode 100644 index 0000000000..2e078b3fcd --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php @@ -0,0 +1,23 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.CoreRequest</code> + */ +class CoreRequest extends \Google\Protobuf\Internal\Message +{ + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php new file mode 100644 index 0000000000..85cb3418ad --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php @@ -0,0 +1,56 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.CoreResponse</code> + */ +class CoreResponse extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Number of cores available on the server + * </pre> + * + * <code>int32 cores = 1;</code> + */ + private $cores = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Number of cores available on the server + * </pre> + * + * <code>int32 cores = 1;</code> + */ + public function getCores() + { + return $this->cores; + } + + /** + * <pre> + * Number of cores available on the server + * </pre> + * + * <code>int32 cores = 1;</code> + */ + public function setCores($var) + { + GPBUtil::checkInt32($var); + $this->cores = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php b/src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php new file mode 100644 index 0000000000..27340fb0ef --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php @@ -0,0 +1,70 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * A protobuf representation for grpc status. This is used by test + * clients to specify a status that the server should attempt to return. + * </pre> + * + * Protobuf type <code>grpc.testing.EchoStatus</code> + */ +class EchoStatus extends \Google\Protobuf\Internal\Message +{ + /** + * <code>int32 code = 1;</code> + */ + private $code = 0; + /** + * <code>string message = 2;</code> + */ + private $message = ''; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <code>int32 code = 1;</code> + */ + public function getCode() + { + return $this->code; + } + + /** + * <code>int32 code = 1;</code> + */ + public function setCode($var) + { + GPBUtil::checkInt32($var); + $this->code = $var; + } + + /** + * <code>string message = 2;</code> + */ + public function getMessage() + { + return $this->message; + } + + /** + * <code>string message = 2;</code> + */ + public function setMessage($var) + { + GPBUtil::checkString($var, True); + $this->message = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php new file mode 100644 index 0000000000..056da6e5de --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php @@ -0,0 +1,153 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/stats.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Histogram data based on grpc/support/histogram.c + * </pre> + * + * Protobuf type <code>grpc.testing.HistogramData</code> + */ +class HistogramData extends \Google\Protobuf\Internal\Message +{ + /** + * <code>repeated uint32 bucket = 1;</code> + */ + private $bucket; + /** + * <code>double min_seen = 2;</code> + */ + private $min_seen = 0.0; + /** + * <code>double max_seen = 3;</code> + */ + private $max_seen = 0.0; + /** + * <code>double sum = 4;</code> + */ + private $sum = 0.0; + /** + * <code>double sum_of_squares = 5;</code> + */ + private $sum_of_squares = 0.0; + /** + * <code>double count = 6;</code> + */ + private $count = 0.0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); + parent::__construct(); + } + + /** + * <code>repeated uint32 bucket = 1;</code> + */ + public function getBucket() + { + return $this->bucket; + } + + /** + * <code>repeated uint32 bucket = 1;</code> + */ + public function setBucket(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::UINT32); + $this->bucket = $var; + } + + /** + * <code>double min_seen = 2;</code> + */ + public function getMinSeen() + { + return $this->min_seen; + } + + /** + * <code>double min_seen = 2;</code> + */ + public function setMinSeen($var) + { + GPBUtil::checkDouble($var); + $this->min_seen = $var; + } + + /** + * <code>double max_seen = 3;</code> + */ + public function getMaxSeen() + { + return $this->max_seen; + } + + /** + * <code>double max_seen = 3;</code> + */ + public function setMaxSeen($var) + { + GPBUtil::checkDouble($var); + $this->max_seen = $var; + } + + /** + * <code>double sum = 4;</code> + */ + public function getSum() + { + return $this->sum; + } + + /** + * <code>double sum = 4;</code> + */ + public function setSum($var) + { + GPBUtil::checkDouble($var); + $this->sum = $var; + } + + /** + * <code>double sum_of_squares = 5;</code> + */ + public function getSumOfSquares() + { + return $this->sum_of_squares; + } + + /** + * <code>double sum_of_squares = 5;</code> + */ + public function setSumOfSquares($var) + { + GPBUtil::checkDouble($var); + $this->sum_of_squares = $var; + } + + /** + * <code>double count = 6;</code> + */ + public function getCount() + { + return $this->count; + } + + /** + * <code>double count = 6;</code> + */ + public function setCount($var) + { + GPBUtil::checkDouble($var); + $this->count = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php new file mode 100644 index 0000000000..836c94b01d --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php @@ -0,0 +1,93 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/stats.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Histogram params based on grpc/support/histogram.c + * </pre> + * + * Protobuf type <code>grpc.testing.HistogramParams</code> + */ +class HistogramParams extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * first bucket is [0, 1 + resolution) + * </pre> + * + * <code>double resolution = 1;</code> + */ + private $resolution = 0.0; + /** + * <pre> + * use enough buckets to allow this value + * </pre> + * + * <code>double max_possible = 2;</code> + */ + private $max_possible = 0.0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * first bucket is [0, 1 + resolution) + * </pre> + * + * <code>double resolution = 1;</code> + */ + public function getResolution() + { + return $this->resolution; + } + + /** + * <pre> + * first bucket is [0, 1 + resolution) + * </pre> + * + * <code>double resolution = 1;</code> + */ + public function setResolution($var) + { + GPBUtil::checkDouble($var); + $this->resolution = $var; + } + + /** + * <pre> + * use enough buckets to allow this value + * </pre> + * + * <code>double max_possible = 2;</code> + */ + public function getMaxPossible() + { + return $this->max_possible; + } + + /** + * <pre> + * use enough buckets to allow this value + * </pre> + * + * <code>double max_possible = 2;</code> + */ + public function setMaxPossible($var) + { + GPBUtil::checkDouble($var); + $this->max_possible = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php new file mode 100644 index 0000000000..1f32e49c8a --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php @@ -0,0 +1,63 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.LoadParams</code> + */ +class LoadParams extends \Google\Protobuf\Internal\Message +{ + protected $load; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>.grpc.testing.ClosedLoopParams closed_loop = 1;</code> + */ + public function getClosedLoop() + { + return $this->readOneof(1); + } + + /** + * <code>.grpc.testing.ClosedLoopParams closed_loop = 1;</code> + */ + public function setClosedLoop(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ClosedLoopParams::class); + $this->writeOneof(1, $var); + } + + /** + * <code>.grpc.testing.PoissonParams poisson = 2;</code> + */ + public function getPoisson() + { + return $this->readOneof(2); + } + + /** + * <code>.grpc.testing.PoissonParams poisson = 2;</code> + */ + public function setPoisson(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\PoissonParams::class); + $this->writeOneof(2, $var); + } + + public function getLoad() + { + return $this->whichOneof("load"); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Mark.php b/src/php/tests/qps/generated_code/Grpc/Testing/Mark.php new file mode 100644 index 0000000000..ce006efacd --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/Mark.php @@ -0,0 +1,60 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Request current stats + * </pre> + * + * Protobuf type <code>grpc.testing.Mark</code> + */ +class Mark extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * if true, the stats will be reset after taking their snapshot. + * </pre> + * + * <code>bool reset = 1;</code> + */ + private $reset = false; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * if true, the stats will be reset after taking their snapshot. + * </pre> + * + * <code>bool reset = 1;</code> + */ + public function getReset() + { + return $this->reset; + } + + /** + * <pre> + * if true, the stats will be reset after taking their snapshot. + * </pre> + * + * <code>bool reset = 1;</code> + */ + public function setReset($var) + { + GPBUtil::checkBool($var); + $this->reset = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Payload.php b/src/php/tests/qps/generated_code/Grpc/Testing/Payload.php new file mode 100644 index 0000000000..d17c271af7 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/Payload.php @@ -0,0 +1,96 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * A block of data, to simply increase gRPC message size. + * </pre> + * + * Protobuf type <code>grpc.testing.Payload</code> + */ +class Payload extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * The type of data in body. + * </pre> + * + * <code>.grpc.testing.PayloadType type = 1;</code> + */ + private $type = 0; + /** + * <pre> + * Primary contents of payload. + * </pre> + * + * <code>bytes body = 2;</code> + */ + private $body = ''; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * The type of data in body. + * </pre> + * + * <code>.grpc.testing.PayloadType type = 1;</code> + */ + public function getType() + { + return $this->type; + } + + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * The type of data in body. + * </pre> + * + * <code>.grpc.testing.PayloadType type = 1;</code> + */ + public function setType($var) + { + GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class); + $this->type = $var; + } + + /** + * <pre> + * Primary contents of payload. + * </pre> + * + * <code>bytes body = 2;</code> + */ + public function getBody() + { + return $this->body; + } + + /** + * <pre> + * Primary contents of payload. + * </pre> + * + * <code>bytes body = 2;</code> + */ + public function setBody($var) + { + GPBUtil::checkString($var, False); + $this->body = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php new file mode 100644 index 0000000000..a2fe7109ba --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php @@ -0,0 +1,80 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/payloads.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.PayloadConfig</code> + */ +class PayloadConfig extends \Google\Protobuf\Internal\Message +{ + protected $payload; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); + parent::__construct(); + } + + /** + * <code>.grpc.testing.ByteBufferParams bytebuf_params = 1;</code> + */ + public function getBytebufParams() + { + return $this->readOneof(1); + } + + /** + * <code>.grpc.testing.ByteBufferParams bytebuf_params = 1;</code> + */ + public function setBytebufParams(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ByteBufferParams::class); + $this->writeOneof(1, $var); + } + + /** + * <code>.grpc.testing.SimpleProtoParams simple_params = 2;</code> + */ + public function getSimpleParams() + { + return $this->readOneof(2); + } + + /** + * <code>.grpc.testing.SimpleProtoParams simple_params = 2;</code> + */ + public function setSimpleParams(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\SimpleProtoParams::class); + $this->writeOneof(2, $var); + } + + /** + * <code>.grpc.testing.ComplexProtoParams complex_params = 3;</code> + */ + public function getComplexParams() + { + return $this->readOneof(3); + } + + /** + * <code>.grpc.testing.ComplexProtoParams complex_params = 3;</code> + */ + public function setComplexParams(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ComplexProtoParams::class); + $this->writeOneof(3, $var); + } + + public function getPayload() + { + return $this->whichOneof("payload"); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php new file mode 100644 index 0000000000..189ef034b4 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php @@ -0,0 +1,26 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +/** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * The type of payload that should be returned. + * </pre> + * + * Protobuf enum <code>grpc.testing.PayloadType</code> + */ +class PayloadType +{ + /** + * <pre> + * Compressable text format. + * </pre> + * + * <code>COMPRESSABLE = 0;</code> + */ + const COMPRESSABLE = 0; +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php new file mode 100644 index 0000000000..d64edd45f0 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php @@ -0,0 +1,61 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Parameters of poisson process distribution, which is a good representation + * of activity coming in from independent identical stationary sources. + * </pre> + * + * Protobuf type <code>grpc.testing.PoissonParams</code> + */ +class PoissonParams extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * The rate of arrivals (a.k.a. lambda parameter of the exp distribution). + * </pre> + * + * <code>double offered_load = 1;</code> + */ + private $offered_load = 0.0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * The rate of arrivals (a.k.a. lambda parameter of the exp distribution). + * </pre> + * + * <code>double offered_load = 1;</code> + */ + public function getOfferedLoad() + { + return $this->offered_load; + } + + /** + * <pre> + * The rate of arrivals (a.k.a. lambda parameter of the exp distribution). + * </pre> + * + * <code>double offered_load = 1;</code> + */ + public function setOfferedLoad($var) + { + GPBUtil::checkDouble($var); + $this->offered_load = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php new file mode 100644 index 0000000000..23c041b470 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php @@ -0,0 +1,72 @@ +<?php +// GENERATED CODE -- DO NOT EDIT! + +// Original file comments: +// Copyright 2017, 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. +// +namespace Grpc\Testing { + + class ProxyClientServiceClient extends \Grpc\BaseStub { + + /** + * @param string $hostname hostname + * @param array $opts channel options + * @param Grpc\Channel $channel (optional) re-use channel object + */ + public function __construct($hostname, $opts, $channel = null) { + parent::__construct($hostname, $opts, $channel); + } + + /** + * @param \Grpc\Testing\Void $argument input argument + * @param array $metadata metadata + * @param array $options call options + */ + public function GetConfig(\Grpc\Testing\Void $argument, + $metadata = [], $options = []) { + return $this->_simpleRequest('/grpc.testing.ProxyClientService/GetConfig', + $argument, + ['\Grpc\Testing\ClientConfig', 'decode'], + $metadata, $options); + } + + /** + * @param array $metadata metadata + * @param array $options call options + */ + public function ReportTime($metadata = [], $options = []) { + return $this->_clientStreamRequest('/grpc.testing.ProxyClientService/ReportTime', + ['\Grpc\Testing\Void','decode'], + $metadata, $options); + } + + } + +} diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php new file mode 100644 index 0000000000..ed43be99ce --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php @@ -0,0 +1,44 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/proxy-service.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ProxyStat</code> + */ +class ProxyStat extends \Google\Protobuf\Internal\Message +{ + /** + * <code>double latency = 1;</code> + */ + private $latency = 0.0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\ProxyService::initOnce(); + parent::__construct(); + } + + /** + * <code>double latency = 1;</code> + */ + public function getLatency() + { + return $this->latency; + } + + /** + * <code>double latency = 1;</code> + */ + public function setLatency($var) + { + GPBUtil::checkDouble($var); + $this->latency = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php new file mode 100644 index 0000000000..dfaaa606c3 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php @@ -0,0 +1,71 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * For reconnect interop test only. + * Server tells client whether its reconnects are following the spec and the + * reconnect backoffs it saw. + * </pre> + * + * Protobuf type <code>grpc.testing.ReconnectInfo</code> + */ +class ReconnectInfo extends \Google\Protobuf\Internal\Message +{ + /** + * <code>bool passed = 1;</code> + */ + private $passed = false; + /** + * <code>repeated int32 backoff_ms = 2;</code> + */ + private $backoff_ms; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <code>bool passed = 1;</code> + */ + public function getPassed() + { + return $this->passed; + } + + /** + * <code>bool passed = 1;</code> + */ + public function setPassed($var) + { + GPBUtil::checkBool($var); + $this->passed = $var; + } + + /** + * <code>repeated int32 backoff_ms = 2;</code> + */ + public function getBackoffMs() + { + return $this->backoff_ms; + } + + /** + * <code>repeated int32 backoff_ms = 2;</code> + */ + public function setBackoffMs(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); + $this->backoff_ms = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php new file mode 100644 index 0000000000..9715855783 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php @@ -0,0 +1,49 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * For reconnect interop test only. + * Client tells server what reconnection parameters it used. + * </pre> + * + * Protobuf type <code>grpc.testing.ReconnectParams</code> + */ +class ReconnectParams extends \Google\Protobuf\Internal\Message +{ + /** + * <code>int32 max_reconnect_backoff_ms = 1;</code> + */ + private $max_reconnect_backoff_ms = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <code>int32 max_reconnect_backoff_ms = 1;</code> + */ + public function getMaxReconnectBackoffMs() + { + return $this->max_reconnect_backoff_ms; + } + + /** + * <code>int32 max_reconnect_backoff_ms = 1;</code> + */ + public function setMaxReconnectBackoffMs($var) + { + GPBUtil::checkInt32($var); + $this->max_reconnect_backoff_ms = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php b/src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php new file mode 100644 index 0000000000..1be42b2ac9 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php @@ -0,0 +1,65 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/stats.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.RequestResultCount</code> + */ +class RequestResultCount extends \Google\Protobuf\Internal\Message +{ + /** + * <code>int32 status_code = 1;</code> + */ + private $status_code = 0; + /** + * <code>int64 count = 2;</code> + */ + private $count = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); + parent::__construct(); + } + + /** + * <code>int32 status_code = 1;</code> + */ + public function getStatusCode() + { + return $this->status_code; + } + + /** + * <code>int32 status_code = 1;</code> + */ + public function setStatusCode($var) + { + GPBUtil::checkInt32($var); + $this->status_code = $var; + } + + /** + * <code>int64 count = 2;</code> + */ + public function getCount() + { + return $this->count; + } + + /** + * <code>int64 count = 2;</code> + */ + public function setCount($var) + { + GPBUtil::checkInt64($var); + $this->count = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php b/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php new file mode 100644 index 0000000000..b7a8e5ece7 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php @@ -0,0 +1,138 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Configuration for a particular response. + * </pre> + * + * Protobuf type <code>grpc.testing.ResponseParameters</code> + */ +class ResponseParameters extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Desired payload sizes in responses from the server. + * </pre> + * + * <code>int32 size = 1;</code> + */ + private $size = 0; + /** + * <pre> + * Desired interval between consecutive responses in the response stream in + * microseconds. + * </pre> + * + * <code>int32 interval_us = 2;</code> + */ + private $interval_us = 0; + /** + * <pre> + * Whether to request the server to compress the response. This field is + * "nullable" in order to interoperate seamlessly with clients not able to + * implement the full compression tests by introspecting the call to verify + * the response's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue compressed = 3;</code> + */ + private $compressed = null; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Desired payload sizes in responses from the server. + * </pre> + * + * <code>int32 size = 1;</code> + */ + public function getSize() + { + return $this->size; + } + + /** + * <pre> + * Desired payload sizes in responses from the server. + * </pre> + * + * <code>int32 size = 1;</code> + */ + public function setSize($var) + { + GPBUtil::checkInt32($var); + $this->size = $var; + } + + /** + * <pre> + * Desired interval between consecutive responses in the response stream in + * microseconds. + * </pre> + * + * <code>int32 interval_us = 2;</code> + */ + public function getIntervalUs() + { + return $this->interval_us; + } + + /** + * <pre> + * Desired interval between consecutive responses in the response stream in + * microseconds. + * </pre> + * + * <code>int32 interval_us = 2;</code> + */ + public function setIntervalUs($var) + { + GPBUtil::checkInt32($var); + $this->interval_us = $var; + } + + /** + * <pre> + * Whether to request the server to compress the response. This field is + * "nullable" in order to interoperate seamlessly with clients not able to + * implement the full compression tests by introspecting the call to verify + * the response's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue compressed = 3;</code> + */ + public function getCompressed() + { + return $this->compressed; + } + + /** + * <pre> + * Whether to request the server to compress the response. This field is + * "nullable" in order to interoperate seamlessly with clients not able to + * implement the full compression tests by introspecting the call to verify + * the response's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue compressed = 3;</code> + */ + public function setCompressed(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); + $this->compressed = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php b/src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php new file mode 100644 index 0000000000..2e664fff47 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php @@ -0,0 +1,21 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +/** + * Protobuf enum <code>grpc.testing.RpcType</code> + */ +class RpcType +{ + /** + * <code>UNARY = 0;</code> + */ + const UNARY = 0; + /** + * <code>STREAMING = 1;</code> + */ + const STREAMING = 1; +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php b/src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php new file mode 100644 index 0000000000..136ed299ea --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php @@ -0,0 +1,291 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * A single performance scenario: input to qps_json_driver + * </pre> + * + * Protobuf type <code>grpc.testing.Scenario</code> + */ +class Scenario extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Human readable name for this scenario + * </pre> + * + * <code>string name = 1;</code> + */ + private $name = ''; + /** + * <pre> + * Client configuration + * </pre> + * + * <code>.grpc.testing.ClientConfig client_config = 2;</code> + */ + private $client_config = null; + /** + * <pre> + * Number of clients to start for the test + * </pre> + * + * <code>int32 num_clients = 3;</code> + */ + private $num_clients = 0; + /** + * <pre> + * Server configuration + * </pre> + * + * <code>.grpc.testing.ServerConfig server_config = 4;</code> + */ + private $server_config = null; + /** + * <pre> + * Number of servers to start for the test + * </pre> + * + * <code>int32 num_servers = 5;</code> + */ + private $num_servers = 0; + /** + * <pre> + * Warmup period, in seconds + * </pre> + * + * <code>int32 warmup_seconds = 6;</code> + */ + private $warmup_seconds = 0; + /** + * <pre> + * Benchmark time, in seconds + * </pre> + * + * <code>int32 benchmark_seconds = 7;</code> + */ + private $benchmark_seconds = 0; + /** + * <pre> + * Number of workers to spawn locally (usually zero) + * </pre> + * + * <code>int32 spawn_local_worker_count = 8;</code> + */ + private $spawn_local_worker_count = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Human readable name for this scenario + * </pre> + * + * <code>string name = 1;</code> + */ + public function getName() + { + return $this->name; + } + + /** + * <pre> + * Human readable name for this scenario + * </pre> + * + * <code>string name = 1;</code> + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + } + + /** + * <pre> + * Client configuration + * </pre> + * + * <code>.grpc.testing.ClientConfig client_config = 2;</code> + */ + public function getClientConfig() + { + return $this->client_config; + } + + /** + * <pre> + * Client configuration + * </pre> + * + * <code>.grpc.testing.ClientConfig client_config = 2;</code> + */ + public function setClientConfig(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ClientConfig::class); + $this->client_config = $var; + } + + /** + * <pre> + * Number of clients to start for the test + * </pre> + * + * <code>int32 num_clients = 3;</code> + */ + public function getNumClients() + { + return $this->num_clients; + } + + /** + * <pre> + * Number of clients to start for the test + * </pre> + * + * <code>int32 num_clients = 3;</code> + */ + public function setNumClients($var) + { + GPBUtil::checkInt32($var); + $this->num_clients = $var; + } + + /** + * <pre> + * Server configuration + * </pre> + * + * <code>.grpc.testing.ServerConfig server_config = 4;</code> + */ + public function getServerConfig() + { + return $this->server_config; + } + + /** + * <pre> + * Server configuration + * </pre> + * + * <code>.grpc.testing.ServerConfig server_config = 4;</code> + */ + public function setServerConfig(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ServerConfig::class); + $this->server_config = $var; + } + + /** + * <pre> + * Number of servers to start for the test + * </pre> + * + * <code>int32 num_servers = 5;</code> + */ + public function getNumServers() + { + return $this->num_servers; + } + + /** + * <pre> + * Number of servers to start for the test + * </pre> + * + * <code>int32 num_servers = 5;</code> + */ + public function setNumServers($var) + { + GPBUtil::checkInt32($var); + $this->num_servers = $var; + } + + /** + * <pre> + * Warmup period, in seconds + * </pre> + * + * <code>int32 warmup_seconds = 6;</code> + */ + public function getWarmupSeconds() + { + return $this->warmup_seconds; + } + + /** + * <pre> + * Warmup period, in seconds + * </pre> + * + * <code>int32 warmup_seconds = 6;</code> + */ + public function setWarmupSeconds($var) + { + GPBUtil::checkInt32($var); + $this->warmup_seconds = $var; + } + + /** + * <pre> + * Benchmark time, in seconds + * </pre> + * + * <code>int32 benchmark_seconds = 7;</code> + */ + public function getBenchmarkSeconds() + { + return $this->benchmark_seconds; + } + + /** + * <pre> + * Benchmark time, in seconds + * </pre> + * + * <code>int32 benchmark_seconds = 7;</code> + */ + public function setBenchmarkSeconds($var) + { + GPBUtil::checkInt32($var); + $this->benchmark_seconds = $var; + } + + /** + * <pre> + * Number of workers to spawn locally (usually zero) + * </pre> + * + * <code>int32 spawn_local_worker_count = 8;</code> + */ + public function getSpawnLocalWorkerCount() + { + return $this->spawn_local_worker_count; + } + + /** + * <pre> + * Number of workers to spawn locally (usually zero) + * </pre> + * + * <code>int32 spawn_local_worker_count = 8;</code> + */ + public function setSpawnLocalWorkerCount($var) + { + GPBUtil::checkInt32($var); + $this->spawn_local_worker_count = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php new file mode 100644 index 0000000000..809cd96244 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php @@ -0,0 +1,312 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Results of a single benchmark scenario. + * </pre> + * + * Protobuf type <code>grpc.testing.ScenarioResult</code> + */ +class ScenarioResult extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Inputs used to run the scenario. + * </pre> + * + * <code>.grpc.testing.Scenario scenario = 1;</code> + */ + private $scenario = null; + /** + * <pre> + * Histograms from all clients merged into one histogram. + * </pre> + * + * <code>.grpc.testing.HistogramData latencies = 2;</code> + */ + private $latencies = null; + /** + * <pre> + * Client stats for each client + * </pre> + * + * <code>repeated .grpc.testing.ClientStats client_stats = 3;</code> + */ + private $client_stats; + /** + * <pre> + * Server stats for each server + * </pre> + * + * <code>repeated .grpc.testing.ServerStats server_stats = 4;</code> + */ + private $server_stats; + /** + * <pre> + * Number of cores available to each server + * </pre> + * + * <code>repeated int32 server_cores = 5;</code> + */ + private $server_cores; + /** + * <pre> + * An after-the-fact computed summary + * </pre> + * + * <code>.grpc.testing.ScenarioResultSummary summary = 6;</code> + */ + private $summary = null; + /** + * <pre> + * Information on success or failure of each worker + * </pre> + * + * <code>repeated bool client_success = 7;</code> + */ + private $client_success; + /** + * <code>repeated bool server_success = 8;</code> + */ + private $server_success; + /** + * <pre> + * Number of failed requests (one row per status code seen) + * </pre> + * + * <code>repeated .grpc.testing.RequestResultCount request_results = 9;</code> + */ + private $request_results; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Inputs used to run the scenario. + * </pre> + * + * <code>.grpc.testing.Scenario scenario = 1;</code> + */ + public function getScenario() + { + return $this->scenario; + } + + /** + * <pre> + * Inputs used to run the scenario. + * </pre> + * + * <code>.grpc.testing.Scenario scenario = 1;</code> + */ + public function setScenario(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Scenario::class); + $this->scenario = $var; + } + + /** + * <pre> + * Histograms from all clients merged into one histogram. + * </pre> + * + * <code>.grpc.testing.HistogramData latencies = 2;</code> + */ + public function getLatencies() + { + return $this->latencies; + } + + /** + * <pre> + * Histograms from all clients merged into one histogram. + * </pre> + * + * <code>.grpc.testing.HistogramData latencies = 2;</code> + */ + public function setLatencies(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\HistogramData::class); + $this->latencies = $var; + } + + /** + * <pre> + * Client stats for each client + * </pre> + * + * <code>repeated .grpc.testing.ClientStats client_stats = 3;</code> + */ + public function getClientStats() + { + return $this->client_stats; + } + + /** + * <pre> + * Client stats for each client + * </pre> + * + * <code>repeated .grpc.testing.ClientStats client_stats = 3;</code> + */ + public function setClientStats(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ClientStats::class); + $this->client_stats = $var; + } + + /** + * <pre> + * Server stats for each server + * </pre> + * + * <code>repeated .grpc.testing.ServerStats server_stats = 4;</code> + */ + public function getServerStats() + { + return $this->server_stats; + } + + /** + * <pre> + * Server stats for each server + * </pre> + * + * <code>repeated .grpc.testing.ServerStats server_stats = 4;</code> + */ + public function setServerStats(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ServerStats::class); + $this->server_stats = $var; + } + + /** + * <pre> + * Number of cores available to each server + * </pre> + * + * <code>repeated int32 server_cores = 5;</code> + */ + public function getServerCores() + { + return $this->server_cores; + } + + /** + * <pre> + * Number of cores available to each server + * </pre> + * + * <code>repeated int32 server_cores = 5;</code> + */ + public function setServerCores(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); + $this->server_cores = $var; + } + + /** + * <pre> + * An after-the-fact computed summary + * </pre> + * + * <code>.grpc.testing.ScenarioResultSummary summary = 6;</code> + */ + public function getSummary() + { + return $this->summary; + } + + /** + * <pre> + * An after-the-fact computed summary + * </pre> + * + * <code>.grpc.testing.ScenarioResultSummary summary = 6;</code> + */ + public function setSummary(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ScenarioResultSummary::class); + $this->summary = $var; + } + + /** + * <pre> + * Information on success or failure of each worker + * </pre> + * + * <code>repeated bool client_success = 7;</code> + */ + public function getClientSuccess() + { + return $this->client_success; + } + + /** + * <pre> + * Information on success or failure of each worker + * </pre> + * + * <code>repeated bool client_success = 7;</code> + */ + public function setClientSuccess(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::BOOL); + $this->client_success = $var; + } + + /** + * <code>repeated bool server_success = 8;</code> + */ + public function getServerSuccess() + { + return $this->server_success; + } + + /** + * <code>repeated bool server_success = 8;</code> + */ + public function setServerSuccess(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::BOOL); + $this->server_success = $var; + } + + /** + * <pre> + * Number of failed requests (one row per status code seen) + * </pre> + * + * <code>repeated .grpc.testing.RequestResultCount request_results = 9;</code> + */ + public function getRequestResults() + { + return $this->request_results; + } + + /** + * <pre> + * Number of failed requests (one row per status code seen) + * </pre> + * + * <code>repeated .grpc.testing.RequestResultCount request_results = 9;</code> + */ + public function setRequestResults(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\RequestResultCount::class); + $this->request_results = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php new file mode 100644 index 0000000000..7520cff78e --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php @@ -0,0 +1,430 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Basic summary that can be computed from ClientStats and ServerStats + * once the scenario has finished. + * </pre> + * + * Protobuf type <code>grpc.testing.ScenarioResultSummary</code> + */ +class ScenarioResultSummary extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Total number of operations per second over all clients. + * </pre> + * + * <code>double qps = 1;</code> + */ + private $qps = 0.0; + /** + * <pre> + * QPS per one server core. + * </pre> + * + * <code>double qps_per_server_core = 2;</code> + */ + private $qps_per_server_core = 0.0; + /** + * <pre> + * server load based on system_time (0.85 => 85%) + * </pre> + * + * <code>double server_system_time = 3;</code> + */ + private $server_system_time = 0.0; + /** + * <pre> + * server load based on user_time (0.85 => 85%) + * </pre> + * + * <code>double server_user_time = 4;</code> + */ + private $server_user_time = 0.0; + /** + * <pre> + * client load based on system_time (0.85 => 85%) + * </pre> + * + * <code>double client_system_time = 5;</code> + */ + private $client_system_time = 0.0; + /** + * <pre> + * client load based on user_time (0.85 => 85%) + * </pre> + * + * <code>double client_user_time = 6;</code> + */ + private $client_user_time = 0.0; + /** + * <pre> + * X% latency percentiles (in nanoseconds) + * </pre> + * + * <code>double latency_50 = 7;</code> + */ + private $latency_50 = 0.0; + /** + * <code>double latency_90 = 8;</code> + */ + private $latency_90 = 0.0; + /** + * <code>double latency_95 = 9;</code> + */ + private $latency_95 = 0.0; + /** + * <code>double latency_99 = 10;</code> + */ + private $latency_99 = 0.0; + /** + * <code>double latency_999 = 11;</code> + */ + private $latency_999 = 0.0; + /** + * <pre> + * server cpu usage percentage + * </pre> + * + * <code>double server_cpu_usage = 12;</code> + */ + private $server_cpu_usage = 0.0; + /** + * <pre> + * Number of requests that succeeded/failed + * </pre> + * + * <code>double successful_requests_per_second = 13;</code> + */ + private $successful_requests_per_second = 0.0; + /** + * <code>double failed_requests_per_second = 14;</code> + */ + private $failed_requests_per_second = 0.0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Total number of operations per second over all clients. + * </pre> + * + * <code>double qps = 1;</code> + */ + public function getQps() + { + return $this->qps; + } + + /** + * <pre> + * Total number of operations per second over all clients. + * </pre> + * + * <code>double qps = 1;</code> + */ + public function setQps($var) + { + GPBUtil::checkDouble($var); + $this->qps = $var; + } + + /** + * <pre> + * QPS per one server core. + * </pre> + * + * <code>double qps_per_server_core = 2;</code> + */ + public function getQpsPerServerCore() + { + return $this->qps_per_server_core; + } + + /** + * <pre> + * QPS per one server core. + * </pre> + * + * <code>double qps_per_server_core = 2;</code> + */ + public function setQpsPerServerCore($var) + { + GPBUtil::checkDouble($var); + $this->qps_per_server_core = $var; + } + + /** + * <pre> + * server load based on system_time (0.85 => 85%) + * </pre> + * + * <code>double server_system_time = 3;</code> + */ + public function getServerSystemTime() + { + return $this->server_system_time; + } + + /** + * <pre> + * server load based on system_time (0.85 => 85%) + * </pre> + * + * <code>double server_system_time = 3;</code> + */ + public function setServerSystemTime($var) + { + GPBUtil::checkDouble($var); + $this->server_system_time = $var; + } + + /** + * <pre> + * server load based on user_time (0.85 => 85%) + * </pre> + * + * <code>double server_user_time = 4;</code> + */ + public function getServerUserTime() + { + return $this->server_user_time; + } + + /** + * <pre> + * server load based on user_time (0.85 => 85%) + * </pre> + * + * <code>double server_user_time = 4;</code> + */ + public function setServerUserTime($var) + { + GPBUtil::checkDouble($var); + $this->server_user_time = $var; + } + + /** + * <pre> + * client load based on system_time (0.85 => 85%) + * </pre> + * + * <code>double client_system_time = 5;</code> + */ + public function getClientSystemTime() + { + return $this->client_system_time; + } + + /** + * <pre> + * client load based on system_time (0.85 => 85%) + * </pre> + * + * <code>double client_system_time = 5;</code> + */ + public function setClientSystemTime($var) + { + GPBUtil::checkDouble($var); + $this->client_system_time = $var; + } + + /** + * <pre> + * client load based on user_time (0.85 => 85%) + * </pre> + * + * <code>double client_user_time = 6;</code> + */ + public function getClientUserTime() + { + return $this->client_user_time; + } + + /** + * <pre> + * client load based on user_time (0.85 => 85%) + * </pre> + * + * <code>double client_user_time = 6;</code> + */ + public function setClientUserTime($var) + { + GPBUtil::checkDouble($var); + $this->client_user_time = $var; + } + + /** + * <pre> + * X% latency percentiles (in nanoseconds) + * </pre> + * + * <code>double latency_50 = 7;</code> + */ + public function getLatency50() + { + return $this->latency_50; + } + + /** + * <pre> + * X% latency percentiles (in nanoseconds) + * </pre> + * + * <code>double latency_50 = 7;</code> + */ + public function setLatency50($var) + { + GPBUtil::checkDouble($var); + $this->latency_50 = $var; + } + + /** + * <code>double latency_90 = 8;</code> + */ + public function getLatency90() + { + return $this->latency_90; + } + + /** + * <code>double latency_90 = 8;</code> + */ + public function setLatency90($var) + { + GPBUtil::checkDouble($var); + $this->latency_90 = $var; + } + + /** + * <code>double latency_95 = 9;</code> + */ + public function getLatency95() + { + return $this->latency_95; + } + + /** + * <code>double latency_95 = 9;</code> + */ + public function setLatency95($var) + { + GPBUtil::checkDouble($var); + $this->latency_95 = $var; + } + + /** + * <code>double latency_99 = 10;</code> + */ + public function getLatency99() + { + return $this->latency_99; + } + + /** + * <code>double latency_99 = 10;</code> + */ + public function setLatency99($var) + { + GPBUtil::checkDouble($var); + $this->latency_99 = $var; + } + + /** + * <code>double latency_999 = 11;</code> + */ + public function getLatency999() + { + return $this->latency_999; + } + + /** + * <code>double latency_999 = 11;</code> + */ + public function setLatency999($var) + { + GPBUtil::checkDouble($var); + $this->latency_999 = $var; + } + + /** + * <pre> + * server cpu usage percentage + * </pre> + * + * <code>double server_cpu_usage = 12;</code> + */ + public function getServerCpuUsage() + { + return $this->server_cpu_usage; + } + + /** + * <pre> + * server cpu usage percentage + * </pre> + * + * <code>double server_cpu_usage = 12;</code> + */ + public function setServerCpuUsage($var) + { + GPBUtil::checkDouble($var); + $this->server_cpu_usage = $var; + } + + /** + * <pre> + * Number of requests that succeeded/failed + * </pre> + * + * <code>double successful_requests_per_second = 13;</code> + */ + public function getSuccessfulRequestsPerSecond() + { + return $this->successful_requests_per_second; + } + + /** + * <pre> + * Number of requests that succeeded/failed + * </pre> + * + * <code>double successful_requests_per_second = 13;</code> + */ + public function setSuccessfulRequestsPerSecond($var) + { + GPBUtil::checkDouble($var); + $this->successful_requests_per_second = $var; + } + + /** + * <code>double failed_requests_per_second = 14;</code> + */ + public function getFailedRequestsPerSecond() + { + return $this->failed_requests_per_second; + } + + /** + * <code>double failed_requests_per_second = 14;</code> + */ + public function setFailedRequestsPerSecond($var) + { + GPBUtil::checkDouble($var); + $this->failed_requests_per_second = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php b/src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php new file mode 100644 index 0000000000..278f555b76 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php @@ -0,0 +1,48 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * A set of scenarios to be run with qps_json_driver + * </pre> + * + * Protobuf type <code>grpc.testing.Scenarios</code> + */ +class Scenarios extends \Google\Protobuf\Internal\Message +{ + /** + * <code>repeated .grpc.testing.Scenario scenarios = 1;</code> + */ + private $scenarios; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>repeated .grpc.testing.Scenario scenarios = 1;</code> + */ + public function getScenarios() + { + return $this->scenarios; + } + + /** + * <code>repeated .grpc.testing.Scenario scenarios = 1;</code> + */ + public function setScenarios(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\Scenario::class); + $this->scenarios = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php new file mode 100644 index 0000000000..27a5b95cc9 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php @@ -0,0 +1,69 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * presence of SecurityParams implies use of TLS + * </pre> + * + * Protobuf type <code>grpc.testing.SecurityParams</code> + */ +class SecurityParams extends \Google\Protobuf\Internal\Message +{ + /** + * <code>bool use_test_ca = 1;</code> + */ + private $use_test_ca = false; + /** + * <code>string server_host_override = 2;</code> + */ + private $server_host_override = ''; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>bool use_test_ca = 1;</code> + */ + public function getUseTestCa() + { + return $this->use_test_ca; + } + + /** + * <code>bool use_test_ca = 1;</code> + */ + public function setUseTestCa($var) + { + GPBUtil::checkBool($var); + $this->use_test_ca = $var; + } + + /** + * <code>string server_host_override = 2;</code> + */ + public function getServerHostOverride() + { + return $this->server_host_override; + } + + /** + * <code>string server_host_override = 2;</code> + */ + public function setServerHostOverride($var) + { + GPBUtil::checkString($var, True); + $this->server_host_override = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php new file mode 100644 index 0000000000..0d84b80124 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php @@ -0,0 +1,63 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ServerArgs</code> + */ +class ServerArgs extends \Google\Protobuf\Internal\Message +{ + protected $argtype; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>.grpc.testing.ServerConfig setup = 1;</code> + */ + public function getSetup() + { + return $this->readOneof(1); + } + + /** + * <code>.grpc.testing.ServerConfig setup = 1;</code> + */ + public function setSetup(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ServerConfig::class); + $this->writeOneof(1, $var); + } + + /** + * <code>.grpc.testing.Mark mark = 2;</code> + */ + public function getMark() + { + return $this->readOneof(2); + } + + /** + * <code>.grpc.testing.Mark mark = 2;</code> + */ + public function setMark(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Mark::class); + $this->writeOneof(2, $var); + } + + public function getArgtype() + { + return $this->whichOneof("argtype"); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php new file mode 100644 index 0000000000..e2bcede48c --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php @@ -0,0 +1,305 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ServerConfig</code> + */ +class ServerConfig extends \Google\Protobuf\Internal\Message +{ + /** + * <code>.grpc.testing.ServerType server_type = 1;</code> + */ + private $server_type = 0; + /** + * <code>.grpc.testing.SecurityParams security_params = 2;</code> + */ + private $security_params = null; + /** + * <pre> + * Port on which to listen. Zero means pick unused port. + * </pre> + * + * <code>int32 port = 4;</code> + */ + private $port = 0; + /** + * <pre> + * Only for async server. Number of threads used to serve the requests. + * </pre> + * + * <code>int32 async_server_threads = 7;</code> + */ + private $async_server_threads = 0; + /** + * <pre> + * Specify the number of cores to limit server to, if desired + * </pre> + * + * <code>int32 core_limit = 8;</code> + */ + private $core_limit = 0; + /** + * <pre> + * payload config, used in generic server. + * Note this must NOT be used in proto (non-generic) servers. For proto servers, + * 'response sizes' must be configured from the 'response_size' field of the + * 'SimpleRequest' objects in RPC requests. + * </pre> + * + * <code>.grpc.testing.PayloadConfig payload_config = 9;</code> + */ + private $payload_config = null; + /** + * <pre> + * Specify the cores we should run the server on, if desired + * </pre> + * + * <code>repeated int32 core_list = 10;</code> + */ + private $core_list; + /** + * <pre> + * If we use an OTHER_SERVER client_type, this string gives more detail + * </pre> + * + * <code>string other_server_api = 11;</code> + */ + private $other_server_api = ''; + /** + * <pre> + * Buffer pool size (no buffer pool specified if unset) + * </pre> + * + * <code>int32 resource_quota_size = 1001;</code> + */ + private $resource_quota_size = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>.grpc.testing.ServerType server_type = 1;</code> + */ + public function getServerType() + { + return $this->server_type; + } + + /** + * <code>.grpc.testing.ServerType server_type = 1;</code> + */ + public function setServerType($var) + { + GPBUtil::checkEnum($var, \Grpc\Testing\ServerType::class); + $this->server_type = $var; + } + + /** + * <code>.grpc.testing.SecurityParams security_params = 2;</code> + */ + public function getSecurityParams() + { + return $this->security_params; + } + + /** + * <code>.grpc.testing.SecurityParams security_params = 2;</code> + */ + public function setSecurityParams(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\SecurityParams::class); + $this->security_params = $var; + } + + /** + * <pre> + * Port on which to listen. Zero means pick unused port. + * </pre> + * + * <code>int32 port = 4;</code> + */ + public function getPort() + { + return $this->port; + } + + /** + * <pre> + * Port on which to listen. Zero means pick unused port. + * </pre> + * + * <code>int32 port = 4;</code> + */ + public function setPort($var) + { + GPBUtil::checkInt32($var); + $this->port = $var; + } + + /** + * <pre> + * Only for async server. Number of threads used to serve the requests. + * </pre> + * + * <code>int32 async_server_threads = 7;</code> + */ + public function getAsyncServerThreads() + { + return $this->async_server_threads; + } + + /** + * <pre> + * Only for async server. Number of threads used to serve the requests. + * </pre> + * + * <code>int32 async_server_threads = 7;</code> + */ + public function setAsyncServerThreads($var) + { + GPBUtil::checkInt32($var); + $this->async_server_threads = $var; + } + + /** + * <pre> + * Specify the number of cores to limit server to, if desired + * </pre> + * + * <code>int32 core_limit = 8;</code> + */ + public function getCoreLimit() + { + return $this->core_limit; + } + + /** + * <pre> + * Specify the number of cores to limit server to, if desired + * </pre> + * + * <code>int32 core_limit = 8;</code> + */ + public function setCoreLimit($var) + { + GPBUtil::checkInt32($var); + $this->core_limit = $var; + } + + /** + * <pre> + * payload config, used in generic server. + * Note this must NOT be used in proto (non-generic) servers. For proto servers, + * 'response sizes' must be configured from the 'response_size' field of the + * 'SimpleRequest' objects in RPC requests. + * </pre> + * + * <code>.grpc.testing.PayloadConfig payload_config = 9;</code> + */ + public function getPayloadConfig() + { + return $this->payload_config; + } + + /** + * <pre> + * payload config, used in generic server. + * Note this must NOT be used in proto (non-generic) servers. For proto servers, + * 'response sizes' must be configured from the 'response_size' field of the + * 'SimpleRequest' objects in RPC requests. + * </pre> + * + * <code>.grpc.testing.PayloadConfig payload_config = 9;</code> + */ + public function setPayloadConfig(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\PayloadConfig::class); + $this->payload_config = $var; + } + + /** + * <pre> + * Specify the cores we should run the server on, if desired + * </pre> + * + * <code>repeated int32 core_list = 10;</code> + */ + public function getCoreList() + { + return $this->core_list; + } + + /** + * <pre> + * Specify the cores we should run the server on, if desired + * </pre> + * + * <code>repeated int32 core_list = 10;</code> + */ + public function setCoreList(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); + $this->core_list = $var; + } + + /** + * <pre> + * If we use an OTHER_SERVER client_type, this string gives more detail + * </pre> + * + * <code>string other_server_api = 11;</code> + */ + public function getOtherServerApi() + { + return $this->other_server_api; + } + + /** + * <pre> + * If we use an OTHER_SERVER client_type, this string gives more detail + * </pre> + * + * <code>string other_server_api = 11;</code> + */ + public function setOtherServerApi($var) + { + GPBUtil::checkString($var, True); + $this->other_server_api = $var; + } + + /** + * <pre> + * Buffer pool size (no buffer pool specified if unset) + * </pre> + * + * <code>int32 resource_quota_size = 1001;</code> + */ + public function getResourceQuotaSize() + { + return $this->resource_quota_size; + } + + /** + * <pre> + * Buffer pool size (no buffer pool specified if unset) + * </pre> + * + * <code>int32 resource_quota_size = 1001;</code> + */ + public function setResourceQuotaSize($var) + { + GPBUtil::checkInt32($var); + $this->resource_quota_size = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php new file mode 100644 index 0000000000..98b2af764c --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php @@ -0,0 +1,191 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/stats.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ServerStats</code> + */ +class ServerStats extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * wall clock time change in seconds since last reset + * </pre> + * + * <code>double time_elapsed = 1;</code> + */ + private $time_elapsed = 0.0; + /** + * <pre> + * change in user time (in seconds) used by the server since last reset + * </pre> + * + * <code>double time_user = 2;</code> + */ + private $time_user = 0.0; + /** + * <pre> + * change in server time (in seconds) used by the server process and all + * threads since last reset + * </pre> + * + * <code>double time_system = 3;</code> + */ + private $time_system = 0.0; + /** + * <pre> + * change in total cpu time of the server (data from proc/stat) + * </pre> + * + * <code>uint64 total_cpu_time = 4;</code> + */ + private $total_cpu_time = 0; + /** + * <pre> + * change in idle time of the server (data from proc/stat) + * </pre> + * + * <code>uint64 idle_cpu_time = 5;</code> + */ + private $idle_cpu_time = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * wall clock time change in seconds since last reset + * </pre> + * + * <code>double time_elapsed = 1;</code> + */ + public function getTimeElapsed() + { + return $this->time_elapsed; + } + + /** + * <pre> + * wall clock time change in seconds since last reset + * </pre> + * + * <code>double time_elapsed = 1;</code> + */ + public function setTimeElapsed($var) + { + GPBUtil::checkDouble($var); + $this->time_elapsed = $var; + } + + /** + * <pre> + * change in user time (in seconds) used by the server since last reset + * </pre> + * + * <code>double time_user = 2;</code> + */ + public function getTimeUser() + { + return $this->time_user; + } + + /** + * <pre> + * change in user time (in seconds) used by the server since last reset + * </pre> + * + * <code>double time_user = 2;</code> + */ + public function setTimeUser($var) + { + GPBUtil::checkDouble($var); + $this->time_user = $var; + } + + /** + * <pre> + * change in server time (in seconds) used by the server process and all + * threads since last reset + * </pre> + * + * <code>double time_system = 3;</code> + */ + public function getTimeSystem() + { + return $this->time_system; + } + + /** + * <pre> + * change in server time (in seconds) used by the server process and all + * threads since last reset + * </pre> + * + * <code>double time_system = 3;</code> + */ + public function setTimeSystem($var) + { + GPBUtil::checkDouble($var); + $this->time_system = $var; + } + + /** + * <pre> + * change in total cpu time of the server (data from proc/stat) + * </pre> + * + * <code>uint64 total_cpu_time = 4;</code> + */ + public function getTotalCpuTime() + { + return $this->total_cpu_time; + } + + /** + * <pre> + * change in total cpu time of the server (data from proc/stat) + * </pre> + * + * <code>uint64 total_cpu_time = 4;</code> + */ + public function setTotalCpuTime($var) + { + GPBUtil::checkUint64($var); + $this->total_cpu_time = $var; + } + + /** + * <pre> + * change in idle time of the server (data from proc/stat) + * </pre> + * + * <code>uint64 idle_cpu_time = 5;</code> + */ + public function getIdleCpuTime() + { + return $this->idle_cpu_time; + } + + /** + * <pre> + * change in idle time of the server (data from proc/stat) + * </pre> + * + * <code>uint64 idle_cpu_time = 5;</code> + */ + public function setIdleCpuTime($var) + { + GPBUtil::checkUint64($var); + $this->idle_cpu_time = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php new file mode 100644 index 0000000000..d293f03fbd --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php @@ -0,0 +1,110 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.ServerStatus</code> + */ +class ServerStatus extends \Google\Protobuf\Internal\Message +{ + /** + * <code>.grpc.testing.ServerStats stats = 1;</code> + */ + private $stats = null; + /** + * <pre> + * the port bound by the server + * </pre> + * + * <code>int32 port = 2;</code> + */ + private $port = 0; + /** + * <pre> + * Number of cores available to the server + * </pre> + * + * <code>int32 cores = 3;</code> + */ + private $cores = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + + /** + * <code>.grpc.testing.ServerStats stats = 1;</code> + */ + public function getStats() + { + return $this->stats; + } + + /** + * <code>.grpc.testing.ServerStats stats = 1;</code> + */ + public function setStats(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\ServerStats::class); + $this->stats = $var; + } + + /** + * <pre> + * the port bound by the server + * </pre> + * + * <code>int32 port = 2;</code> + */ + public function getPort() + { + return $this->port; + } + + /** + * <pre> + * the port bound by the server + * </pre> + * + * <code>int32 port = 2;</code> + */ + public function setPort($var) + { + GPBUtil::checkInt32($var); + $this->port = $var; + } + + /** + * <pre> + * Number of cores available to the server + * </pre> + * + * <code>int32 cores = 3;</code> + */ + public function getCores() + { + return $this->cores; + } + + /** + * <pre> + * Number of cores available to the server + * </pre> + * + * <code>int32 cores = 3;</code> + */ + public function setCores($var) + { + GPBUtil::checkInt32($var); + $this->cores = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php new file mode 100644 index 0000000000..605c83c3f7 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php @@ -0,0 +1,33 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +/** + * Protobuf enum <code>grpc.testing.ServerType</code> + */ +class ServerType +{ + /** + * <code>SYNC_SERVER = 0;</code> + */ + const SYNC_SERVER = 0; + /** + * <code>ASYNC_SERVER = 1;</code> + */ + const ASYNC_SERVER = 1; + /** + * <code>ASYNC_GENERIC_SERVER = 2;</code> + */ + const ASYNC_GENERIC_SERVER = 2; + /** + * <pre> + * used for some language-specific variants + * </pre> + * + * <code>OTHER_SERVER = 3;</code> + */ + const OTHER_SERVER = 3; +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php new file mode 100644 index 0000000000..29834a3be7 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php @@ -0,0 +1,65 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/payloads.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.SimpleProtoParams</code> + */ +class SimpleProtoParams extends \Google\Protobuf\Internal\Message +{ + /** + * <code>int32 req_size = 1;</code> + */ + private $req_size = 0; + /** + * <code>int32 resp_size = 2;</code> + */ + private $resp_size = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); + parent::__construct(); + } + + /** + * <code>int32 req_size = 1;</code> + */ + public function getReqSize() + { + return $this->req_size; + } + + /** + * <code>int32 req_size = 1;</code> + */ + public function setReqSize($var) + { + GPBUtil::checkInt32($var); + $this->req_size = $var; + } + + /** + * <code>int32 resp_size = 2;</code> + */ + public function getRespSize() + { + return $this->resp_size; + } + + /** + * <code>int32 resp_size = 2;</code> + */ + public function setRespSize($var) + { + GPBUtil::checkInt32($var); + $this->resp_size = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php new file mode 100644 index 0000000000..f84c95319f --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php @@ -0,0 +1,306 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Unary request. + * </pre> + * + * Protobuf type <code>grpc.testing.SimpleRequest</code> + */ +class SimpleRequest extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * Desired payload type in the response from the server. + * If response_type is RANDOM, server randomly chooses one from other formats. + * </pre> + * + * <code>.grpc.testing.PayloadType response_type = 1;</code> + */ + private $response_type = 0; + /** + * <pre> + * Desired payload size in the response from the server. + * </pre> + * + * <code>int32 response_size = 2;</code> + */ + private $response_size = 0; + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 3;</code> + */ + private $payload = null; + /** + * <pre> + * Whether SimpleResponse should include username. + * </pre> + * + * <code>bool fill_username = 4;</code> + */ + private $fill_username = false; + /** + * <pre> + * Whether SimpleResponse should include OAuth scope. + * </pre> + * + * <code>bool fill_oauth_scope = 5;</code> + */ + private $fill_oauth_scope = false; + /** + * <pre> + * Whether to request the server to compress the response. This field is + * "nullable" in order to interoperate seamlessly with clients not able to + * implement the full compression tests by introspecting the call to verify + * the response's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue response_compressed = 6;</code> + */ + private $response_compressed = null; + /** + * <pre> + * Whether server should return a given status + * </pre> + * + * <code>.grpc.testing.EchoStatus response_status = 7;</code> + */ + private $response_status = null; + /** + * <pre> + * Whether the server should expect this request to be compressed. + * </pre> + * + * <code>.grpc.testing.BoolValue expect_compressed = 8;</code> + */ + private $expect_compressed = null; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * Desired payload type in the response from the server. + * If response_type is RANDOM, server randomly chooses one from other formats. + * </pre> + * + * <code>.grpc.testing.PayloadType response_type = 1;</code> + */ + public function getResponseType() + { + return $this->response_type; + } + + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * Desired payload type in the response from the server. + * If response_type is RANDOM, server randomly chooses one from other formats. + * </pre> + * + * <code>.grpc.testing.PayloadType response_type = 1;</code> + */ + public function setResponseType($var) + { + GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class); + $this->response_type = $var; + } + + /** + * <pre> + * Desired payload size in the response from the server. + * </pre> + * + * <code>int32 response_size = 2;</code> + */ + public function getResponseSize() + { + return $this->response_size; + } + + /** + * <pre> + * Desired payload size in the response from the server. + * </pre> + * + * <code>int32 response_size = 2;</code> + */ + public function setResponseSize($var) + { + GPBUtil::checkInt32($var); + $this->response_size = $var; + } + + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 3;</code> + */ + public function getPayload() + { + return $this->payload; + } + + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 3;</code> + */ + public function setPayload(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); + $this->payload = $var; + } + + /** + * <pre> + * Whether SimpleResponse should include username. + * </pre> + * + * <code>bool fill_username = 4;</code> + */ + public function getFillUsername() + { + return $this->fill_username; + } + + /** + * <pre> + * Whether SimpleResponse should include username. + * </pre> + * + * <code>bool fill_username = 4;</code> + */ + public function setFillUsername($var) + { + GPBUtil::checkBool($var); + $this->fill_username = $var; + } + + /** + * <pre> + * Whether SimpleResponse should include OAuth scope. + * </pre> + * + * <code>bool fill_oauth_scope = 5;</code> + */ + public function getFillOauthScope() + { + return $this->fill_oauth_scope; + } + + /** + * <pre> + * Whether SimpleResponse should include OAuth scope. + * </pre> + * + * <code>bool fill_oauth_scope = 5;</code> + */ + public function setFillOauthScope($var) + { + GPBUtil::checkBool($var); + $this->fill_oauth_scope = $var; + } + + /** + * <pre> + * Whether to request the server to compress the response. This field is + * "nullable" in order to interoperate seamlessly with clients not able to + * implement the full compression tests by introspecting the call to verify + * the response's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue response_compressed = 6;</code> + */ + public function getResponseCompressed() + { + return $this->response_compressed; + } + + /** + * <pre> + * Whether to request the server to compress the response. This field is + * "nullable" in order to interoperate seamlessly with clients not able to + * implement the full compression tests by introspecting the call to verify + * the response's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue response_compressed = 6;</code> + */ + public function setResponseCompressed(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); + $this->response_compressed = $var; + } + + /** + * <pre> + * Whether server should return a given status + * </pre> + * + * <code>.grpc.testing.EchoStatus response_status = 7;</code> + */ + public function getResponseStatus() + { + return $this->response_status; + } + + /** + * <pre> + * Whether server should return a given status + * </pre> + * + * <code>.grpc.testing.EchoStatus response_status = 7;</code> + */ + public function setResponseStatus(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class); + $this->response_status = $var; + } + + /** + * <pre> + * Whether the server should expect this request to be compressed. + * </pre> + * + * <code>.grpc.testing.BoolValue expect_compressed = 8;</code> + */ + public function getExpectCompressed() + { + return $this->expect_compressed; + } + + /** + * <pre> + * Whether the server should expect this request to be compressed. + * </pre> + * + * <code>.grpc.testing.BoolValue expect_compressed = 8;</code> + */ + public function setExpectCompressed(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); + $this->expect_compressed = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php new file mode 100644 index 0000000000..ccc628ec4c --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php @@ -0,0 +1,129 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Unary response, as configured by the request. + * </pre> + * + * Protobuf type <code>grpc.testing.SimpleResponse</code> + */ +class SimpleResponse extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Payload to increase message size. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + private $payload = null; + /** + * <pre> + * The user the request came from, for verifying authentication was + * successful when the client expected it. + * </pre> + * + * <code>string username = 2;</code> + */ + private $username = ''; + /** + * <pre> + * OAuth scope. + * </pre> + * + * <code>string oauth_scope = 3;</code> + */ + private $oauth_scope = ''; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Payload to increase message size. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + public function getPayload() + { + return $this->payload; + } + + /** + * <pre> + * Payload to increase message size. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + public function setPayload(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); + $this->payload = $var; + } + + /** + * <pre> + * The user the request came from, for verifying authentication was + * successful when the client expected it. + * </pre> + * + * <code>string username = 2;</code> + */ + public function getUsername() + { + return $this->username; + } + + /** + * <pre> + * The user the request came from, for verifying authentication was + * successful when the client expected it. + * </pre> + * + * <code>string username = 2;</code> + */ + public function setUsername($var) + { + GPBUtil::checkString($var, True); + $this->username = $var; + } + + /** + * <pre> + * OAuth scope. + * </pre> + * + * <code>string oauth_scope = 3;</code> + */ + public function getOauthScope() + { + return $this->oauth_scope; + } + + /** + * <pre> + * OAuth scope. + * </pre> + * + * <code>string oauth_scope = 3;</code> + */ + public function setOauthScope($var) + { + GPBUtil::checkString($var, True); + $this->oauth_scope = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php new file mode 100644 index 0000000000..d7bbc70779 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php @@ -0,0 +1,102 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Client-streaming request. + * </pre> + * + * Protobuf type <code>grpc.testing.StreamingInputCallRequest</code> + */ +class StreamingInputCallRequest extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + private $payload = null; + /** + * <pre> + * Whether the server should expect this request to be compressed. This field + * is "nullable" in order to interoperate seamlessly with servers not able to + * implement the full compression tests by introspecting the call to verify + * the request's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue expect_compressed = 2;</code> + */ + private $expect_compressed = null; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + public function getPayload() + { + return $this->payload; + } + + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + public function setPayload(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); + $this->payload = $var; + } + + /** + * <pre> + * Whether the server should expect this request to be compressed. This field + * is "nullable" in order to interoperate seamlessly with servers not able to + * implement the full compression tests by introspecting the call to verify + * the request's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue expect_compressed = 2;</code> + */ + public function getExpectCompressed() + { + return $this->expect_compressed; + } + + /** + * <pre> + * Whether the server should expect this request to be compressed. This field + * is "nullable" in order to interoperate seamlessly with servers not able to + * implement the full compression tests by introspecting the call to verify + * the request's compression status. + * </pre> + * + * <code>.grpc.testing.BoolValue expect_compressed = 2;</code> + */ + public function setExpectCompressed(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); + $this->expect_compressed = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php new file mode 100644 index 0000000000..fdd1d0dbf8 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php @@ -0,0 +1,60 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Client-streaming response. + * </pre> + * + * Protobuf type <code>grpc.testing.StreamingInputCallResponse</code> + */ +class StreamingInputCallResponse extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Aggregated size of payloads received from the client. + * </pre> + * + * <code>int32 aggregated_payload_size = 1;</code> + */ + private $aggregated_payload_size = 0; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Aggregated size of payloads received from the client. + * </pre> + * + * <code>int32 aggregated_payload_size = 1;</code> + */ + public function getAggregatedPayloadSize() + { + return $this->aggregated_payload_size; + } + + /** + * <pre> + * Aggregated size of payloads received from the client. + * </pre> + * + * <code>int32 aggregated_payload_size = 1;</code> + */ + public function setAggregatedPayloadSize($var) + { + GPBUtil::checkInt32($var); + $this->aggregated_payload_size = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php new file mode 100644 index 0000000000..2aab5fadad --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php @@ -0,0 +1,171 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Server-streaming request. + * </pre> + * + * Protobuf type <code>grpc.testing.StreamingOutputCallRequest</code> + */ +class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * Desired payload type in the response from the server. + * If response_type is RANDOM, the payload from each response in the stream + * might be of different types. This is to simulate a mixed type of payload + * stream. + * </pre> + * + * <code>.grpc.testing.PayloadType response_type = 1;</code> + */ + private $response_type = 0; + /** + * <pre> + * Configuration for each expected response message. + * </pre> + * + * <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code> + */ + private $response_parameters; + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 3;</code> + */ + private $payload = null; + /** + * <pre> + * Whether server should return a given status + * </pre> + * + * <code>.grpc.testing.EchoStatus response_status = 7;</code> + */ + private $response_status = null; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * Desired payload type in the response from the server. + * If response_type is RANDOM, the payload from each response in the stream + * might be of different types. This is to simulate a mixed type of payload + * stream. + * </pre> + * + * <code>.grpc.testing.PayloadType response_type = 1;</code> + */ + public function getResponseType() + { + return $this->response_type; + } + + /** + * <pre> + * DEPRECATED, don't use. To be removed shortly. + * Desired payload type in the response from the server. + * If response_type is RANDOM, the payload from each response in the stream + * might be of different types. This is to simulate a mixed type of payload + * stream. + * </pre> + * + * <code>.grpc.testing.PayloadType response_type = 1;</code> + */ + public function setResponseType($var) + { + GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class); + $this->response_type = $var; + } + + /** + * <pre> + * Configuration for each expected response message. + * </pre> + * + * <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code> + */ + public function getResponseParameters() + { + return $this->response_parameters; + } + + /** + * <pre> + * Configuration for each expected response message. + * </pre> + * + * <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code> + */ + public function setResponseParameters(&$var) + { + GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ResponseParameters::class); + $this->response_parameters = $var; + } + + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 3;</code> + */ + public function getPayload() + { + return $this->payload; + } + + /** + * <pre> + * Optional input payload sent along with the request. + * </pre> + * + * <code>.grpc.testing.Payload payload = 3;</code> + */ + public function setPayload(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); + $this->payload = $var; + } + + /** + * <pre> + * Whether server should return a given status + * </pre> + * + * <code>.grpc.testing.EchoStatus response_status = 7;</code> + */ + public function getResponseStatus() + { + return $this->response_status; + } + + /** + * <pre> + * Whether server should return a given status + * </pre> + * + * <code>.grpc.testing.EchoStatus response_status = 7;</code> + */ + public function setResponseStatus(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class); + $this->response_status = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php new file mode 100644 index 0000000000..c06c78c9d8 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php @@ -0,0 +1,60 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/messages.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * <pre> + * Server-streaming response, as configured by the request and parameters. + * </pre> + * + * Protobuf type <code>grpc.testing.StreamingOutputCallResponse</code> + */ +class StreamingOutputCallResponse extends \Google\Protobuf\Internal\Message +{ + /** + * <pre> + * Payload to increase response size. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + private $payload = null; + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); + parent::__construct(); + } + + /** + * <pre> + * Payload to increase response size. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + public function getPayload() + { + return $this->payload; + } + + /** + * <pre> + * Payload to increase response size. + * </pre> + * + * <code>.grpc.testing.Payload payload = 1;</code> + */ + public function setPayload(&$var) + { + GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); + $this->payload = $var; + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Void.php b/src/php/tests/qps/generated_code/Grpc/Testing/Void.php new file mode 100644 index 0000000000..38c100845a --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/Void.php @@ -0,0 +1,23 @@ +<?php +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/control.proto + +namespace Grpc\Testing; + +use Google\Protobuf\Internal\GPBType; +use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\Internal\GPBUtil; + +/** + * Protobuf type <code>grpc.testing.Void</code> + */ +class Void extends \Google\Protobuf\Internal\Message +{ + + public function __construct() { + \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); + parent::__construct(); + } + +} + diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php new file mode 100644 index 0000000000..0a68e41269 --- /dev/null +++ b/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php @@ -0,0 +1,111 @@ +<?php +// GENERATED CODE -- DO NOT EDIT! + +// Original file comments: +// 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. +// +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +namespace Grpc\Testing { + + class WorkerServiceClient extends \Grpc\BaseStub { + + /** + * @param string $hostname hostname + * @param array $opts channel options + * @param Grpc\Channel $channel (optional) re-use channel object + */ + public function __construct($hostname, $opts, $channel = null) { + parent::__construct($hostname, $opts, $channel); + } + + /** + * Start server with specified workload. + * First request sent specifies the ServerConfig followed by ServerStatus + * response. After that, a "Mark" can be sent anytime to request the latest + * stats. Closing the stream will initiate shutdown of the test server + * and once the shutdown has finished, the OK status is sent to terminate + * this RPC. + * @param array $metadata metadata + * @param array $options call options + */ + public function RunServer($metadata = [], $options = []) { + return $this->_bidiRequest('/grpc.testing.WorkerService/RunServer', + ['\Grpc\Testing\ServerStatus','decode'], + $metadata, $options); + } + + /** + * Start client with specified workload. + * First request sent specifies the ClientConfig followed by ClientStatus + * response. After that, a "Mark" can be sent anytime to request the latest + * stats. Closing the stream will initiate shutdown of the test client + * and once the shutdown has finished, the OK status is sent to terminate + * this RPC. + * @param array $metadata metadata + * @param array $options call options + */ + public function RunClient($metadata = [], $options = []) { + return $this->_bidiRequest('/grpc.testing.WorkerService/RunClient', + ['\Grpc\Testing\ClientStatus','decode'], + $metadata, $options); + } + + /** + * Just return the core count - unary call + * @param \Grpc\Testing\CoreRequest $argument input argument + * @param array $metadata metadata + * @param array $options call options + */ + public function CoreCount(\Grpc\Testing\CoreRequest $argument, + $metadata = [], $options = []) { + return $this->_simpleRequest('/grpc.testing.WorkerService/CoreCount', + $argument, + ['\Grpc\Testing\CoreResponse', 'decode'], + $metadata, $options); + } + + /** + * Quit this worker + * @param \Grpc\Testing\Void $argument input argument + * @param array $metadata metadata + * @param array $options call options + */ + public function QuitWorker(\Grpc\Testing\Void $argument, + $metadata = [], $options = []) { + return $this->_simpleRequest('/grpc.testing.WorkerService/QuitWorker', + $argument, + ['\Grpc\Testing\Void', 'decode'], + $metadata, $options); + } + + } + +} diff --git a/src/proto/grpc/testing/proxy-service.proto b/src/proto/grpc/testing/proxy-service.proto new file mode 100644 index 0000000000..7b7de8d549 --- /dev/null +++ b/src/proto/grpc/testing/proxy-service.proto @@ -0,0 +1,44 @@ +// Copyright 2017, 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"; + +import "src/proto/grpc/testing/control.proto"; + +package grpc.testing; + +message ProxyStat { + double latency = 1; +} + +service ProxyClientService { + rpc GetConfig(Void) returns (ClientConfig); + rpc ReportTime(stream ProxyStat) returns (Void); +} + diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index a9f20e6d2a..5fc748483a 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -33,6 +33,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/profiling/basic_timers.c', 'src/core/lib/profiling/stap_timers.c', 'src/core/lib/support/alloc.c', + 'src/core/lib/support/arena.c', 'src/core/lib/support/avl.c', 'src/core/lib/support/backoff.c', 'src/core/lib/support/cmdline.c', @@ -134,6 +135,9 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_common.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', 'src/core/lib/iomgr/tcp_server_windows.c', 'src/core/lib/iomgr/tcp_uv.c', diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index c197e92ca5..267d848e74 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='1.2.0.dev0' +VERSION='1.3.0.dev0' diff --git a/src/python/grpcio_health_checking/grpc_health/v1/health.py b/src/python/grpcio_health_checking/grpc_health/v1/health.py index f0f11cf84b..e92c2659b7 100644 --- a/src/python/grpcio_health_checking/grpc_health/v1/health.py +++ b/src/python/grpcio_health_checking/grpc_health/v1/health.py @@ -33,9 +33,10 @@ import threading import grpc from grpc_health.v1 import health_pb2 +from grpc_health.v1 import health_pb2_grpc -class HealthServicer(health_pb2.HealthServicer): +class HealthServicer(health_pb2_grpc.HealthServicer): """Servicer handling RPCs for service statuses.""" def __init__(self): diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index c1807e9f1c..4ff5e266a1 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION='1.2.0.dev0' +VERSION='1.3.0.dev0' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index 3778dcd3e0..8ffc08c04b 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION='1.2.0.dev0' +VERSION='1.3.0.dev0' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 33824b6b8f..ba82dce6f6 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='1.2.0.dev0' +VERSION='1.3.0.dev0' 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 363b4c5f99..1bc8669dad 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 @@ -34,6 +34,7 @@ import grpc from grpc.framework.foundation import logging_pool from grpc_health.v1 import health from grpc_health.v1 import health_pb2 +from grpc_health.v1 import health_pb2_grpc from tests.unit.framework.common import test_constants @@ -52,11 +53,11 @@ class HealthServicerTest(unittest.TestCase): 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) + health_pb2_grpc.add_HealthServicer_to_server(servicer, self._server) self._server.start() channel = grpc.insecure_channel('localhost:%d' % port) - self._stub = health_pb2.HealthStub(channel) + self._stub = health_pb2_grpc.HealthStub(channel) def test_empty_service(self): request = health_pb2.HealthCheckRequest() diff --git a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py index 58f3b364ba..3325d54375 100644 --- a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py +++ b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py @@ -32,7 +32,7 @@ from concurrent import futures import unittest import grpc -from src.proto.grpc.testing import test_pb2 +from src.proto.grpc.testing import test_pb2_grpc from tests.interop import _intraop_test_case from tests.interop import methods @@ -44,11 +44,11 @@ class InsecureIntraopTest(_intraop_test_case.IntraopTestCase, def setUp(self): self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - test_pb2.add_TestServiceServicer_to_server(methods.TestService(), - self.server) + test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(), + self.server) port = self.server.add_insecure_port('[::]:0') self.server.start() - self.stub = test_pb2.TestServiceStub( + self.stub = test_pb2_grpc.TestServiceStub( grpc.insecure_channel('localhost:{}'.format(port))) diff --git a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py index 5fe929b99e..857e00efb3 100644 --- a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py +++ b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py @@ -32,7 +32,7 @@ from concurrent import futures import unittest import grpc -from src.proto.grpc.testing import test_pb2 +from src.proto.grpc.testing import test_pb2_grpc from tests.interop import _intraop_test_case from tests.interop import methods @@ -45,14 +45,14 @@ class SecureIntraopTest(_intraop_test_case.IntraopTestCase, unittest.TestCase): def setUp(self): self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - test_pb2.add_TestServiceServicer_to_server(methods.TestService(), - self.server) + test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(), + self.server) port = self.server.add_secure_port( '[::]:0', grpc.ssl_server_credentials( [(resources.private_key(), resources.certificate_chain())])) self.server.start() - self.stub = test_pb2.TestServiceStub( + self.stub = test_pb2_grpc.TestServiceStub( grpc.secure_channel('localhost:{}'.format(port), grpc.ssl_channel_credentials( resources.test_root_certificates()), ( diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py index 662ea9ce57..e1016f7c0d 100644 --- a/src/python/grpcio_tests/tests/interop/methods.py +++ b/src/python/grpcio_tests/tests/interop/methods.py @@ -40,7 +40,7 @@ from grpc.beta import implementations from src.proto.grpc.testing import empty_pb2 from src.proto.grpc.testing import messages_pb2 -from src.proto.grpc.testing import test_pb2 +from src.proto.grpc.testing import test_pb2_grpc _INITIAL_METADATA_KEY = "x-grpc-test-echo-initial" _TRAILING_METADATA_KEY = "x-grpc-test-echo-trailing-bin" @@ -66,7 +66,7 @@ def _maybe_echo_status_and_message(request, servicer_context): servicer_context.set_details(request.response_status.message) -class TestService(test_pb2.TestServiceServicer): +class TestService(test_pb2_grpc.TestServiceServicer): def EmptyCall(self, request, context): _maybe_echo_metadata(context) diff --git a/src/python/grpcio_tests/tests/interop/server.py b/src/python/grpcio_tests/tests/interop/server.py index 65f1604eb8..0ae2c97b42 100644 --- a/src/python/grpcio_tests/tests/interop/server.py +++ b/src/python/grpcio_tests/tests/interop/server.py @@ -34,7 +34,7 @@ import logging import time import grpc -from src.proto.grpc.testing import test_pb2 +from src.proto.grpc.testing import test_pb2_grpc from tests.interop import methods from tests.interop import resources @@ -53,7 +53,8 @@ def serve(): args = parser.parse_args() server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - test_pb2.add_TestServiceServicer_to_server(methods.TestService(), server) + test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(), + server) if args.use_tls: private_key = resources.private_key() certificate_chain = resources.certificate_chain() diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py index db938e6545..6f9269dd40 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py @@ -42,6 +42,7 @@ import sys import tempfile import threading import unittest +import platform import grpc from grpc_tools import protoc @@ -150,6 +151,8 @@ class CommonTestMixin(object): self.assertEqual(expected_response, response) +@unittest.skipIf(platform.python_implementation() == "PyPy", + "Skip test if run with PyPy") class SameSeparateTest(unittest.TestCase, SeparateTestMixin): def setUp(self): @@ -191,6 +194,8 @@ class SameSeparateTest(unittest.TestCase, SeparateTestMixin): shutil.rmtree(self.directory) +@unittest.skipIf(platform.python_implementation() == "PyPy", + "Skip test if run with PyPy") class SameCommonTest(unittest.TestCase, CommonTestMixin): def setUp(self): @@ -228,6 +233,8 @@ class SameCommonTest(unittest.TestCase, CommonTestMixin): shutil.rmtree(self.directory) +@unittest.skipIf(platform.python_implementation() == "PyPy", + "Skip test if run with PyPy") class SplitCommonTest(unittest.TestCase, CommonTestMixin): def setUp(self): @@ -277,6 +284,8 @@ class SplitCommonTest(unittest.TestCase, CommonTestMixin): shutil.rmtree(self.directory) +@unittest.skipIf(platform.python_implementation() == "PyPy", + "Skip test if run with PyPy") class SplitSeparateTest(unittest.TestCase, SeparateTestMixin): def setUp(self): diff --git a/src/python/grpcio_tests/tests/qps/qps_worker.py b/src/python/grpcio_tests/tests/qps/qps_worker.py index 025dfb9d4a..7cd53e7bd9 100644 --- a/src/python/grpcio_tests/tests/qps/qps_worker.py +++ b/src/python/grpcio_tests/tests/qps/qps_worker.py @@ -33,7 +33,7 @@ import time from concurrent import futures import grpc -from src.proto.grpc.testing import services_pb2 +from src.proto.grpc.testing import services_pb2_grpc from tests.qps import worker_server @@ -41,7 +41,7 @@ from tests.qps import worker_server def run_worker_server(port): server = grpc.server(futures.ThreadPoolExecutor(max_workers=5)) servicer = worker_server.WorkerServer() - services_pb2.add_WorkerServiceServicer_to_server(servicer, server) + services_pb2_grpc.add_WorkerServiceServicer_to_server(servicer, server) server.add_insecure_port('[::]:{}'.format(port)) server.start() servicer.wait_for_quit() diff --git a/src/python/grpcio_tests/tests/qps/worker_server.py b/src/python/grpcio_tests/tests/qps/worker_server.py index ca1a777611..de9535f46e 100644 --- a/src/python/grpcio_tests/tests/qps/worker_server.py +++ b/src/python/grpcio_tests/tests/qps/worker_server.py @@ -35,7 +35,7 @@ import time 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 services_pb2_grpc from src.proto.grpc.testing import stats_pb2 from tests.qps import benchmark_client @@ -45,7 +45,7 @@ from tests.qps import histogram from tests.unit import resources -class WorkerServer(services_pb2.WorkerServiceServicer): +class WorkerServer(services_pb2_grpc.WorkerServiceServicer): """Python Worker Server implementation.""" def __init__(self): @@ -87,8 +87,8 @@ class WorkerServer(services_pb2.WorkerServiceServicer): futures.ThreadPoolExecutor(max_workers=server_threads)) if config.server_type == control_pb2.ASYNC_SERVER: servicer = benchmark_server.BenchmarkServer() - services_pb2.add_BenchmarkServiceServicer_to_server(servicer, - server) + services_pb2_grpc.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) diff --git a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py index d06ff064e2..4d73be6204 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -34,6 +34,7 @@ import grpc from grpc.framework.foundation import logging_pool from grpc_reflection.v1alpha import reflection from grpc_reflection.v1alpha import reflection_pb2 +from grpc_reflection.v1alpha import reflection_pb2_grpc from google.protobuf import descriptor_pool from google.protobuf import descriptor_pb2 @@ -61,12 +62,12 @@ class ReflectionServicerTest(unittest.TestCase): server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server(server_pool) port = self._server.add_insecure_port('[::]:0') - reflection_pb2.add_ServerReflectionServicer_to_server(servicer, - self._server) + reflection_pb2_grpc.add_ServerReflectionServicer_to_server(servicer, + self._server) self._server.start() channel = grpc.insecure_channel('localhost:%d' % port) - self._stub = reflection_pb2.ServerReflectionStub(channel) + self._stub = reflection_pb2_grpc.ServerReflectionStub(channel) def testFileByName(self): requests = (reflection_pb2.ServerReflectionRequest( diff --git a/src/python/grpcio_tests/tests/stress/client.py b/src/python/grpcio_tests/tests/stress/client.py index b9dbe61d44..b7eb12bff8 100644 --- a/src/python/grpcio_tests/tests/stress/client.py +++ b/src/python/grpcio_tests/tests/stress/client.py @@ -34,7 +34,7 @@ import threading import grpc from six.moves import queue -from src.proto.grpc.testing import metrics_pb2 +from src.proto.grpc.testing import metrics_pb2_grpc from src.proto.grpc.testing import test_pb2 from tests.interop import methods @@ -139,7 +139,7 @@ def run_test(args): runners = [] server = grpc.server(futures.ThreadPoolExecutor(max_workers=25)) - metrics_pb2.add_MetricsServiceServicer_to_server( + metrics_pb2_grpc.add_MetricsServiceServicer_to_server( metrics_server.MetricsServer(hist), server) server.add_insecure_port('[::]:{}'.format(args.metrics_port)) server.start() diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 52465a4dd7..3ef6f0eb29 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -296,6 +296,7 @@ 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_ref_is_unique_type gpr_ref_is_unique_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; @@ -589,6 +590,7 @@ void grpc_rb_load_imports(HMODULE library) { 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_ref_is_unique_import = (gpr_ref_is_unique_type) GetProcAddress(library, "gpr_ref_is_unique"); 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"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 8ec7f6fd95..dccdbe7dc9 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -839,6 +839,9 @@ extern gpr_refn_type 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 int(*gpr_ref_is_unique_type)(gpr_refcount *r); +extern gpr_ref_is_unique_type gpr_ref_is_unique_import; +#define gpr_ref_is_unique gpr_ref_is_unique_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 diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index ce0892decf..9901158e73 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 = '1.2.0.dev' + VERSION = '1.3.0.dev' end diff --git a/src/ruby/qps/proxy-worker.rb b/src/ruby/qps/proxy-worker.rb new file mode 100755 index 0000000000..077920d1d3 --- /dev/null +++ b/src/ruby/qps/proxy-worker.rb @@ -0,0 +1,160 @@ +#!/usr/bin/env ruby + +# Copyright 2017, 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. + +# Proxy of worker service implementation for running a PHP client + +this_dir = File.expand_path(File.dirname(__FILE__)) +lib_dir = File.join(File.dirname(this_dir), 'lib') +$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) +$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) + +require 'grpc' +require 'optparse' +require 'histogram' +require 'etc' +require 'facter' +require 'qps-common' +require 'src/proto/grpc/testing/services_services_pb' +require 'src/proto/grpc/testing/proxy-service_services_pb' + +class ProxyBenchmarkClientServiceImpl < Grpc::Testing::ProxyClientService::Service + def initialize(port) + @mytarget = "localhost:" + port.to_s + end + def setup(config) + @config = config + @histres = config.histogram_params.resolution + @histmax = config.histogram_params.max_possible + @histogram = Histogram.new(@histres, @histmax) + @start_time = Time.now + # TODO(vjpai): Support multiple client channels by spawning off a PHP client per channel + command = "php " + File.expand_path(File.dirname(__FILE__)) + "/../../php/tests/qps/client.php " + @mytarget + puts "Starting command: " + command + @php_pid = spawn(command) + end + def stop + Process.kill("TERM", @php_pid) + Process.wait(@php_pid) + end + def get_config(_args, _call) + puts "Answering get_config" + @config + end + def report_time(call) + puts "Starting a time reporting stream" + call.each_remote_read do |lat| + @histogram.add((lat.latency)*1e9) + end + Grpc::Testing::Void.new + end + def mark(reset) + lat = Grpc::Testing::HistogramData.new( + bucket: @histogram.contents, + min_seen: @histogram.minimum, + max_seen: @histogram.maximum, + sum: @histogram.sum, + sum_of_squares: @histogram.sum_of_squares, + count: @histogram.count + ) + elapsed = Time.now-@start_time + if reset + @start_time = Time.now + @histogram = Histogram.new(@histres, @histmax) + end + Grpc::Testing::ClientStats.new(latencies: lat, time_elapsed: elapsed) + end +end + +class ProxyWorkerServiceImpl < Grpc::Testing::WorkerService::Service + def cpu_cores + Facter.value('processors')['count'] + end + # Leave run_server unimplemented since this proxies for a client only. + # If the driver tries to use this as a server, it will get an unimplemented + # status return value. + def run_client(reqs) + q = EnumeratorQueue.new(self) + Thread.new { + reqs.each do |req| + case req.argtype.to_s + when 'setup' + @bmc.setup(req.setup) + q.push(Grpc::Testing::ClientStatus.new(stats: @bmc.mark(false))) + when 'mark' + q.push(Grpc::Testing::ClientStatus.new(stats: + @bmc.mark(req.mark.reset))) + end + end + @bmc.stop + q.push(self) + } + q.each_item + end + def core_count(_args, _call) + Grpc::Testing::CoreResponse.new(cores: cpu_cores) + end + def quit_worker(_args, _call) + Thread.new { + sleep 3 + @server.stop + } + Grpc::Testing::Void.new + end + def initialize(s, bmc) + @server = s + @bmc = bmc + end +end + +def proxymain + options = { + 'driver_port' => 0 + } + OptionParser.new do |opts| + opts.banner = 'Usage: [--driver_port <port>]' + opts.on('--driver_port PORT', '<port>') do |v| + options['driver_port'] = v + end + end.parse! + + # Configure any errors with client or server child threads to surface + Thread.abort_on_exception = true + + s = GRPC::RpcServer.new + port = s.add_http2_port("0.0.0.0:" + options['driver_port'].to_s, + :this_port_is_insecure) + bmc = ProxyBenchmarkClientServiceImpl.new(port) + s.handle(bmc) + s.handle(ProxyWorkerServiceImpl.new(s, bmc)) + s.run +end + +proxymain diff --git a/src/ruby/qps/src/proto/grpc/testing/proxy-service_pb.rb b/src/ruby/qps/src/proto/grpc/testing/proxy-service_pb.rb new file mode 100644 index 0000000000..d238198cca --- /dev/null +++ b/src/ruby/qps/src/proto/grpc/testing/proxy-service_pb.rb @@ -0,0 +1,17 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: src/proto/grpc/testing/proxy-service.proto + +require 'google/protobuf' + +require 'src/proto/grpc/testing/control_pb' +Google::Protobuf::DescriptorPool.generated_pool.build do + add_message "grpc.testing.ProxyStat" do + optional :latency, :double, 1 + end +end + +module Grpc + module Testing + ProxyStat = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ProxyStat").msgclass + end +end diff --git a/src/ruby/qps/src/proto/grpc/testing/proxy-service_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/proxy-service_services_pb.rb new file mode 100644 index 0000000000..37ddbf5b03 --- /dev/null +++ b/src/ruby/qps/src/proto/grpc/testing/proxy-service_services_pb.rb @@ -0,0 +1,55 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# Source: src/proto/grpc/testing/proxy-service.proto for package 'grpc.testing' +# Original file comments: +# Copyright 2017, 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. +# + +require 'grpc' +require 'src/proto/grpc/testing/proxy-service_pb' + +module Grpc + module Testing + module ProxyClientService + class Service + + include GRPC::GenericService + + self.marshal_class_method = :encode + self.unmarshal_class_method = :decode + self.service_name = 'grpc.testing.ProxyClientService' + + rpc :GetConfig, Void, ClientConfig + rpc :ReportTime, stream(ProxyStat), Void + end + + Stub = Service.rpc_stub_class + end + end +end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 8f3d2ba81c..632c0100bd 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '1.2.0.dev' + VERSION = '1.3.0.dev' end end |