|
|
|
@ -46,21 +46,38 @@ typedef struct grpc_rb_server { |
|
|
|
|
/* The actual server */ |
|
|
|
|
grpc_server* wrapped; |
|
|
|
|
grpc_completion_queue* queue; |
|
|
|
|
gpr_atm shutdown_started; |
|
|
|
|
int shutdown_and_notify_done; |
|
|
|
|
int destroy_done; |
|
|
|
|
} grpc_rb_server; |
|
|
|
|
|
|
|
|
|
static void destroy_server(grpc_rb_server* server, gpr_timespec deadline) { |
|
|
|
|
static void grpc_rb_server_maybe_shutdown_and_notify(grpc_rb_server* server, |
|
|
|
|
gpr_timespec deadline) { |
|
|
|
|
grpc_event ev; |
|
|
|
|
// This can be started by app or implicitly by GC. Avoid a race between these.
|
|
|
|
|
if (gpr_atm_full_fetch_add(&server->shutdown_started, (gpr_atm)1) == 0) { |
|
|
|
|
void* tag = &ev; |
|
|
|
|
if (!server->shutdown_and_notify_done) { |
|
|
|
|
server->shutdown_and_notify_done = 1; |
|
|
|
|
if (server->wrapped != NULL) { |
|
|
|
|
grpc_server_shutdown_and_notify(server->wrapped, server->queue, NULL); |
|
|
|
|
ev = rb_completion_queue_pluck(server->queue, NULL, deadline, NULL); |
|
|
|
|
grpc_server_shutdown_and_notify(server->wrapped, server->queue, tag); |
|
|
|
|
ev = rb_completion_queue_pluck(server->queue, tag, deadline, NULL); |
|
|
|
|
if (ev.type == GRPC_QUEUE_TIMEOUT) { |
|
|
|
|
grpc_server_cancel_all_calls(server->wrapped); |
|
|
|
|
rb_completion_queue_pluck(server->queue, NULL, |
|
|
|
|
gpr_inf_future(GPR_CLOCK_REALTIME), NULL); |
|
|
|
|
ev = rb_completion_queue_pluck( |
|
|
|
|
server->queue, tag, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); |
|
|
|
|
} |
|
|
|
|
if (ev.type != GRPC_OP_COMPLETE) { |
|
|
|
|
gpr_log(GPR_INFO, |
|
|
|
|
"GRPC_RUBY: bad grpc_server_shutdown_and_notify result:%d", |
|
|
|
|
ev.type); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void grpc_rb_server_maybe_destroy(grpc_rb_server* server) { |
|
|
|
|
// This can be started by app or implicitly by GC. Avoid a race between these.
|
|
|
|
|
if (!server->destroy_done) { |
|
|
|
|
server->destroy_done = 1; |
|
|
|
|
if (server->wrapped != NULL) { |
|
|
|
|
grpc_server_destroy(server->wrapped); |
|
|
|
|
grpc_rb_completion_queue_destroy(server->queue); |
|
|
|
|
server->wrapped = NULL; |
|
|
|
@ -81,7 +98,8 @@ static void grpc_rb_server_free(void* p) { |
|
|
|
|
deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), |
|
|
|
|
gpr_time_from_seconds(2, GPR_TIMESPAN)); |
|
|
|
|
|
|
|
|
|
destroy_server(svr, deadline); |
|
|
|
|
grpc_rb_server_maybe_shutdown_and_notify(svr, deadline); |
|
|
|
|
grpc_rb_server_maybe_destroy(svr); |
|
|
|
|
|
|
|
|
|
xfree(p); |
|
|
|
|
} |
|
|
|
@ -107,7 +125,8 @@ static const rb_data_type_t grpc_rb_server_data_type = { |
|
|
|
|
static VALUE grpc_rb_server_alloc(VALUE cls) { |
|
|
|
|
grpc_rb_server* wrapper = ALLOC(grpc_rb_server); |
|
|
|
|
wrapper->wrapped = NULL; |
|
|
|
|
wrapper->shutdown_started = (gpr_atm)0; |
|
|
|
|
wrapper->destroy_done = 0; |
|
|
|
|
wrapper->shutdown_and_notify_done = 0; |
|
|
|
|
return TypedData_Wrap_Struct(cls, &grpc_rb_server_data_type, wrapper); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -232,25 +251,10 @@ static VALUE grpc_rb_server_start(VALUE self) { |
|
|
|
|
return Qnil; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
call-seq: |
|
|
|
|
server = Server.new({'arg1': 'value1'}) |
|
|
|
|
... // do stuff with server
|
|
|
|
|
... |
|
|
|
|
... // to shutdown the server
|
|
|
|
|
server.destroy() |
|
|
|
|
|
|
|
|
|
... // to shutdown the server with a timeout
|
|
|
|
|
server.destroy(timeout) |
|
|
|
|
|
|
|
|
|
Destroys server instances. */ |
|
|
|
|
static VALUE grpc_rb_server_destroy(int argc, VALUE* argv, VALUE self) { |
|
|
|
|
VALUE timeout = Qnil; |
|
|
|
|
static VALUE grpc_rb_server_shutdown_and_notify(VALUE self, VALUE timeout) { |
|
|
|
|
gpr_timespec deadline; |
|
|
|
|
grpc_rb_server* s = NULL; |
|
|
|
|
|
|
|
|
|
/* "01" == 0 mandatory args, 1 (timeout) is optional */ |
|
|
|
|
rb_scan_args(argc, argv, "01", &timeout); |
|
|
|
|
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s); |
|
|
|
|
if (TYPE(timeout) == T_NIL) { |
|
|
|
|
deadline = gpr_inf_future(GPR_CLOCK_REALTIME); |
|
|
|
@ -258,8 +262,26 @@ static VALUE grpc_rb_server_destroy(int argc, VALUE* argv, VALUE self) { |
|
|
|
|
deadline = grpc_rb_time_timeval(timeout, /* absolute time*/ 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
destroy_server(s, deadline); |
|
|
|
|
grpc_rb_server_maybe_shutdown_and_notify(s, deadline); |
|
|
|
|
|
|
|
|
|
return Qnil; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
call-seq: |
|
|
|
|
server = Server.new({'arg1': 'value1'}) |
|
|
|
|
... // do stuff with server
|
|
|
|
|
... |
|
|
|
|
... // initiate server shutdown
|
|
|
|
|
server.shutdown_and_notify(timeout) |
|
|
|
|
... // to shutdown the server
|
|
|
|
|
server.destroy() |
|
|
|
|
|
|
|
|
|
Destroys server instances. */ |
|
|
|
|
static VALUE grpc_rb_server_destroy(VALUE self) { |
|
|
|
|
grpc_rb_server* s = NULL; |
|
|
|
|
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s); |
|
|
|
|
grpc_rb_server_maybe_destroy(s); |
|
|
|
|
return Qnil; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -326,7 +348,9 @@ void Init_grpc_server() { |
|
|
|
|
rb_define_method(grpc_rb_cServer, "request_call", grpc_rb_server_request_call, |
|
|
|
|
0); |
|
|
|
|
rb_define_method(grpc_rb_cServer, "start", grpc_rb_server_start, 0); |
|
|
|
|
rb_define_method(grpc_rb_cServer, "destroy", grpc_rb_server_destroy, -1); |
|
|
|
|
rb_define_method(grpc_rb_cServer, "shutdown_and_notify", |
|
|
|
|
grpc_rb_server_shutdown_and_notify, 1); |
|
|
|
|
rb_define_method(grpc_rb_cServer, "destroy", grpc_rb_server_destroy, 0); |
|
|
|
|
rb_define_alias(grpc_rb_cServer, "close", "destroy"); |
|
|
|
|
rb_define_method(grpc_rb_cServer, "add_http2_port", |
|
|
|
|
grpc_rb_server_add_http2_port, 2); |
|
|
|
|