Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(731)

Unified Diff: third_party/grpc/src/ruby/ext/grpc/rb_grpc.c

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/grpc/src/ruby/ext/grpc/rb_grpc.c
diff --git a/third_party/grpc/src/ruby/ext/grpc/rb_grpc.c b/third_party/grpc/src/ruby/ext/grpc/rb_grpc.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b18fa212a44278d80222f653bc59f483d44d1
--- /dev/null
+++ b/third_party/grpc/src/ruby/ext/grpc/rb_grpc.c
@@ -0,0 +1,337 @@
+/*
+ *
+ * Copyright 2015-2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <ruby/ruby.h>
+#include "rb_grpc_imports.generated.h"
+#include "rb_grpc.h"
+
+#include <math.h>
+#include <ruby/ruby.h>
+#include <ruby/vm.h>
+#include <sys/time.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/time.h>
+#include "rb_call.h"
+#include "rb_call_credentials.h"
+#include "rb_channel.h"
+#include "rb_channel_credentials.h"
+#include "rb_completion_queue.h"
+#include "rb_loader.h"
+#include "rb_server.h"
+#include "rb_server_credentials.h"
+
+static VALUE grpc_rb_cTimeVal = Qnil;
+
+static rb_data_type_t grpc_rb_timespec_data_type = {
+ "gpr_timespec",
+ {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE,
+ {NULL, NULL}},
+ NULL,
+ NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+ RUBY_TYPED_FREE_IMMEDIATELY
+#endif
+};
+
+/* Alloc func that blocks allocation of a given object by raising an
+ * exception. */
+VALUE grpc_rb_cannot_alloc(VALUE cls) {
+ rb_raise(rb_eTypeError,
+ "allocation of %s only allowed from the gRPC native layer",
+ rb_class2name(cls));
+ return Qnil;
+}
+
+/* Init func that fails by raising an exception. */
+VALUE grpc_rb_cannot_init(VALUE self) {
+ rb_raise(rb_eTypeError,
+ "initialization of %s only allowed from the gRPC native layer",
+ rb_obj_classname(self));
+ return Qnil;
+}
+
+/* Init/Clone func that fails by raising an exception. */
+VALUE grpc_rb_cannot_init_copy(VALUE copy, VALUE self) {
+ (void)self;
+ rb_raise(rb_eTypeError,
+ "initialization of %s only allowed from the gRPC native layer",
+ rb_obj_classname(copy));
+ return Qnil;
+}
+
+/* id_tv_{,u}sec are accessor methods on Ruby Time instances. */
+static ID id_tv_sec;
+static ID id_tv_nsec;
+
+/**
+ * grpc_rb_time_timeval creates a timeval from a ruby time object.
+ *
+ * This func is copied from ruby source, MRI/source/time.c, which is published
+ * under the same license as the ruby.h, on which the entire extensions is
+ * based.
+ */
+gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) {
+ gpr_timespec t;
+ gpr_timespec *time_const;
+ const char *tstr = interval ? "time interval" : "time";
+ const char *want = " want <secs from epoch>|<Time>|<GRPC::TimeConst.*>";
+
+ t.clock_type = GPR_CLOCK_REALTIME;
+ switch (TYPE(time)) {
+ case T_DATA:
+ if (CLASS_OF(time) == grpc_rb_cTimeVal) {
+ TypedData_Get_Struct(time, gpr_timespec, &grpc_rb_timespec_data_type,
+ time_const);
+ t = *time_const;
+ } else if (CLASS_OF(time) == rb_cTime) {
+ t.tv_sec = NUM2INT(rb_funcall(time, id_tv_sec, 0));
+ t.tv_nsec = NUM2INT(rb_funcall(time, id_tv_nsec, 0));
+ } else {
+ rb_raise(rb_eTypeError, "bad input: (%s)->c_timeval, got <%s>,%s", tstr,
+ rb_obj_classname(time), want);
+ }
+ break;
+
+ case T_FIXNUM:
+ t.tv_sec = FIX2LONG(time);
+ if (interval && t.tv_sec < 0)
+ rb_raise(rb_eArgError, "%s must be positive", tstr);
+ t.tv_nsec = 0;
+ break;
+
+ case T_FLOAT:
+ if (interval && RFLOAT_VALUE(time) < 0.0)
+ rb_raise(rb_eArgError, "%s must be positive", tstr);
+ else {
+ double f, d;
+
+ d = modf(RFLOAT_VALUE(time), &f);
+ if (d < 0) {
+ d += 1;
+ f -= 1;
+ }
+ t.tv_sec = (int64_t)f;
+ if (f != t.tv_sec) {
+ rb_raise(rb_eRangeError, "%f out of Time range",
+ RFLOAT_VALUE(time));
+ }
+ t.tv_nsec = (int)(d * 1e9 + 0.5);
+ }
+ break;
+
+ case T_BIGNUM:
+ t.tv_sec = NUM2LONG(time);
+ if (interval && t.tv_sec < 0)
+ rb_raise(rb_eArgError, "%s must be positive", tstr);
+ t.tv_nsec = 0;
+ break;
+
+ default:
+ rb_raise(rb_eTypeError, "bad input: (%s)->c_timeval, got <%s>,%s", tstr,
+ rb_obj_classname(time), want);
+ break;
+ }
+ return t;
+}
+
+static void Init_grpc_status_codes() {
+ /* Constants representing the status codes or grpc_status_code in status.h */
+ VALUE grpc_rb_mStatusCodes =
+ rb_define_module_under(grpc_rb_mGrpcCore, "StatusCodes");
+ rb_define_const(grpc_rb_mStatusCodes, "OK", INT2NUM(GRPC_STATUS_OK));
+ rb_define_const(grpc_rb_mStatusCodes, "CANCELLED",
+ INT2NUM(GRPC_STATUS_CANCELLED));
+ rb_define_const(grpc_rb_mStatusCodes, "UNKNOWN",
+ INT2NUM(GRPC_STATUS_UNKNOWN));
+ rb_define_const(grpc_rb_mStatusCodes, "INVALID_ARGUMENT",
+ INT2NUM(GRPC_STATUS_INVALID_ARGUMENT));
+ rb_define_const(grpc_rb_mStatusCodes, "DEADLINE_EXCEEDED",
+ INT2NUM(GRPC_STATUS_DEADLINE_EXCEEDED));
+ rb_define_const(grpc_rb_mStatusCodes, "NOT_FOUND",
+ INT2NUM(GRPC_STATUS_NOT_FOUND));
+ rb_define_const(grpc_rb_mStatusCodes, "ALREADY_EXISTS",
+ INT2NUM(GRPC_STATUS_ALREADY_EXISTS));
+ rb_define_const(grpc_rb_mStatusCodes, "PERMISSION_DENIED",
+ INT2NUM(GRPC_STATUS_PERMISSION_DENIED));
+ rb_define_const(grpc_rb_mStatusCodes, "UNAUTHENTICATED",
+ INT2NUM(GRPC_STATUS_UNAUTHENTICATED));
+ rb_define_const(grpc_rb_mStatusCodes, "RESOURCE_EXHAUSTED",
+ INT2NUM(GRPC_STATUS_RESOURCE_EXHAUSTED));
+ rb_define_const(grpc_rb_mStatusCodes, "FAILED_PRECONDITION",
+ INT2NUM(GRPC_STATUS_FAILED_PRECONDITION));
+ rb_define_const(grpc_rb_mStatusCodes, "ABORTED",
+ INT2NUM(GRPC_STATUS_ABORTED));
+ rb_define_const(grpc_rb_mStatusCodes, "OUT_OF_RANGE",
+ INT2NUM(GRPC_STATUS_OUT_OF_RANGE));
+ rb_define_const(grpc_rb_mStatusCodes, "UNIMPLEMENTED",
+ INT2NUM(GRPC_STATUS_UNIMPLEMENTED));
+ rb_define_const(grpc_rb_mStatusCodes, "INTERNAL",
+ INT2NUM(GRPC_STATUS_INTERNAL));
+ rb_define_const(grpc_rb_mStatusCodes, "UNAVAILABLE",
+ INT2NUM(GRPC_STATUS_UNAVAILABLE));
+ rb_define_const(grpc_rb_mStatusCodes, "DATA_LOSS",
+ INT2NUM(GRPC_STATUS_DATA_LOSS));
+}
+
+/* id_at is the constructor method of the ruby standard Time class. */
+static ID id_at;
+
+/* id_inspect is the inspect method found on various ruby objects. */
+static ID id_inspect;
+
+/* id_to_s is the to_s method found on various ruby objects. */
+static ID id_to_s;
+
+/* Converts a wrapped time constant to a standard time. */
+static VALUE grpc_rb_time_val_to_time(VALUE self) {
+ gpr_timespec *time_const = NULL;
+ gpr_timespec real_time;
+ TypedData_Get_Struct(self, gpr_timespec, &grpc_rb_timespec_data_type,
+ time_const);
+ real_time = gpr_convert_clock_type(*time_const, GPR_CLOCK_REALTIME);
+ return rb_funcall(rb_cTime, id_at, 2, INT2NUM(real_time.tv_sec),
+ INT2NUM(real_time.tv_nsec));
+}
+
+/* Invokes inspect on the ctime version of the time val. */
+static VALUE grpc_rb_time_val_inspect(VALUE self) {
+ return rb_funcall(grpc_rb_time_val_to_time(self), id_inspect, 0);
+}
+
+/* Invokes to_s on the ctime version of the time val. */
+static VALUE grpc_rb_time_val_to_s(VALUE self) {
+ return rb_funcall(grpc_rb_time_val_to_time(self), id_to_s, 0);
+}
+
+static gpr_timespec zero_realtime;
+static gpr_timespec inf_future_realtime;
+static gpr_timespec inf_past_realtime;
+
+/* Adds a module with constants that map to gpr's static timeval structs. */
+static void Init_grpc_time_consts() {
+ VALUE grpc_rb_mTimeConsts =
+ rb_define_module_under(grpc_rb_mGrpcCore, "TimeConsts");
+ grpc_rb_cTimeVal =
+ rb_define_class_under(grpc_rb_mGrpcCore, "TimeSpec", rb_cObject);
+ zero_realtime = gpr_time_0(GPR_CLOCK_REALTIME);
+ inf_future_realtime = gpr_inf_future(GPR_CLOCK_REALTIME);
+ inf_past_realtime = gpr_inf_past(GPR_CLOCK_REALTIME);
+ rb_define_const(
+ grpc_rb_mTimeConsts, "ZERO",
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
+ (void *)&zero_realtime));
+ rb_define_const(
+ grpc_rb_mTimeConsts, "INFINITE_FUTURE",
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
+ (void *)&inf_future_realtime));
+ rb_define_const(
+ grpc_rb_mTimeConsts, "INFINITE_PAST",
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
+ (void *)&inf_past_realtime));
+ rb_define_method(grpc_rb_cTimeVal, "to_time", grpc_rb_time_val_to_time, 0);
+ rb_define_method(grpc_rb_cTimeVal, "inspect", grpc_rb_time_val_inspect, 0);
+ rb_define_method(grpc_rb_cTimeVal, "to_s", grpc_rb_time_val_to_s, 0);
+ id_at = rb_intern("at");
+ id_inspect = rb_intern("inspect");
+ id_to_s = rb_intern("to_s");
+ id_tv_sec = rb_intern("tv_sec");
+ id_tv_nsec = rb_intern("tv_nsec");
+}
+
+static void grpc_rb_shutdown(void) {
+ grpc_shutdown();
+}
+
+/* Initialize the GRPC module structs */
+
+/* grpc_rb_sNewServerRpc is the struct that holds new server rpc details. */
+VALUE grpc_rb_sNewServerRpc = Qnil;
+/* grpc_rb_sStatus is the struct that holds status details. */
+VALUE grpc_rb_sStatus = Qnil;
+
+/* Initialize the GRPC module. */
+VALUE grpc_rb_mGRPC = Qnil;
+VALUE grpc_rb_mGrpcCore = Qnil;
+
+/* cached Symbols for members in Status struct */
+VALUE sym_code = Qundef;
+VALUE sym_details = Qundef;
+VALUE sym_metadata = Qundef;
+
+static gpr_once g_once_init = GPR_ONCE_INIT;
+
+static void grpc_ruby_once_init() {
+ grpc_init();
+ atexit(grpc_rb_shutdown);
+}
+
+void Init_grpc_c() {
+ if (!grpc_rb_load_core()) {
+ rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
+ return;
+ }
+
+ /* ruby_vm_at_exit doesn't seem to be working. It would crash once every
+ * blue moon, and some users are getting it repeatedly. See the discussions
+ * - https://github.com/grpc/grpc/pull/5337
+ * - https://bugs.ruby-lang.org/issues/12095
+ *
+ * In order to still be able to handle the (unlikely) situation where the
+ * extension is loaded by a first Ruby VM that is subsequently destroyed,
+ * then loaded again by another VM within the same process, we need to
+ * schedule our initialization and destruction only once.
+ */
+ gpr_once_init(&g_once_init, grpc_ruby_once_init);
+
+ grpc_rb_mGRPC = rb_define_module("GRPC");
+ grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
+ grpc_rb_sNewServerRpc =
+ rb_struct_define("NewServerRpc", "method", "host",
+ "deadline", "metadata", "call", NULL);
+ grpc_rb_sStatus =
+ rb_struct_define("Status", "code", "details", "metadata", NULL);
+ sym_code = ID2SYM(rb_intern("code"));
+ sym_details = ID2SYM(rb_intern("details"));
+ sym_metadata = ID2SYM(rb_intern("metadata"));
+
+ Init_grpc_channel();
+ Init_grpc_completion_queue();
+ Init_grpc_call();
+ Init_grpc_call_credentials();
+ Init_grpc_channel_credentials();
+ Init_grpc_server();
+ Init_grpc_server_credentials();
+ Init_grpc_status_codes();
+ Init_grpc_time_consts();
+}
« no previous file with comments | « third_party/grpc/src/ruby/ext/grpc/rb_grpc.h ('k') | third_party/grpc/src/ruby/ext/grpc/rb_grpc_imports.generated.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698