Merge branch 'master' into server_channel_affinity

pull/6149/head
Sree Kuchibhotla 9 years ago
commit b69251c2f6
  1. 15
      doc/fail_fast.md
  2. 22
      examples/node/greeter_client.js
  3. 12
      examples/node/greeter_server.js
  4. 39
      examples/node/helloworld_grpc_pb.js
  5. 332
      examples/node/helloworld_pb.js
  6. 1
      examples/node/package.json
  7. 7
      include/grpc++/impl/codegen/call.h
  8. 2
      src/core/ext/client_config/subchannel.c
  9. 17
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  10. 11
      src/core/ext/transport/chttp2/transport/internal.h
  11. 21
      src/core/ext/transport/chttp2/transport/parsing.c
  12. 22
      src/core/lib/channel/compress_filter.c
  13. 2
      src/core/lib/channel/compress_filter.h
  14. 29
      src/core/lib/iomgr/tcp_client_windows.c
  15. 1
      src/core/lib/surface/init.c
  16. 109
      src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
  17. 13
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  18. 4
      src/node/tools/bin/protoc.js
  19. 6
      src/node/tools/bin/protoc_plugin.js
  20. 54
      src/objective-c/GRPCClient/GRPCCall.m
  21. 6
      src/objective-c/tests/InteropTests.m
  22. 28
      src/python/grpcio/tests/stress/__init__.py
  23. 132
      src/python/grpcio/tests/stress/client.py
  24. 60
      src/python/grpcio/tests/stress/metrics_server.py
  25. 73
      src/python/grpcio/tests/stress/test_runner.py
  26. 38
      src/ruby/ext/grpc/extconf.rb
  27. 12
      src/ruby/tools/README.md
  28. 41
      src/ruby/tools/bin/protoc.rb
  29. 41
      src/ruby/tools/bin/protoc_grpc_ruby_plugin.rb
  30. 22
      src/ruby/tools/grpc-tools.gemspec
  31. 45
      src/ruby/tools/os_check.rb
  32. 34
      src/ruby/tools/version.rb
  33. 36
      templates/src/ruby/tools/version.rb.template
  34. 41
      templates/tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile.template
  35. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/03a72675e1969f836094f1ecfec2a7b34418e306
  36. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/0416afd6875d9ba55f1e5f86a6456a5445d5e576
  37. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/08c42ef29eff83052c5887855f2fa3e07ebe470c
  38. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/1ba889ea1543297824e99e641e6ca8b91f45732e
  39. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/3b09bf453c6f93983c24c4d5481e55d66213f93a
  40. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/49cb33cbb60f041e8e99dd718993acd2c3354416
  41. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/59743fe120be6ae1aed1c02230ee1bb460f621ee
  42. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/a5ccb8f124d8ddb5350b90bc0d6b96db280cb7c9
  43. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/a7fac1265a384fe9e45a9ee3d708b79c4e80505e
  44. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/aaf049720c707d4e14e47e7eb31d6a2dda60e66a
  45. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/c4e4c7572e005e18d56eac407033da058737a5ab
  46. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/crash-dae0f07934a527989f23f06e630710ff6ca8c809
  47. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/e96ad9c17795e52edc810a08d4fc61fe8790002a
  48. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/fa202a5f51cd49f8ea5af60c5f403f797c01c504
  49. 8
      test/core/util/passthru_endpoint.c
  50. 2
      test/core/util/test_config.c
  51. 12
      test/cpp/qps/client.h
  52. 3
      test/cpp/qps/driver.cc
  53. 9
      tools/buildgen/plugins/list_api.py
  54. 101
      tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile
  55. 47
      tools/dockerfile/stress_test/grpc_interop_stress_csharp/build_interop_stress.sh
  56. 24
      tools/run_tests/build_package_ruby.sh
  57. 3
      tools/run_tests/performance/kill_workers.sh
  58. 90
      tools/run_tests/stress_test/configs/csharp.json
  59. 224
      tools/run_tests/tests.json

@ -0,0 +1,15 @@
gRPC Fail Fast Semantics
========================
Fail fast requests allow terminating requests (with status UNAVAILABLE) prior
to the deadline of the request being met.
gRPC implementations of fail fast can terminate requests whenever a channel is
in the TRANSIENT_FAILURE or SHUTDOWN states. If the channel is in any other
state (CONNECTING, READY, or IDLE) the request should not be terminated.
Fail fast SHOULD be the default for gRPC implementations, with an option to
switch to non fail fast.
The opposite of fail fast is 'ignore connectivity'.

@ -31,30 +31,22 @@
*
*/
var grpc = require('grpc');
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var hello_messages = require('./helloworld_pb');
var hello_service = require('./helloworld_grpc_pb');
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
function main() {
var client = new hello_service.GreeterClient('localhost:50051',
grpc.credentials.createInsecure());
var client = new hello_proto.Greeter('localhost:50051',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
var request = new hello_messages.HelloRequest();
request.setName(user);
client.sayHello(request, function(err, response) {
if (err) {
debugger;
throw err;
}
console.log('Greeting:', response.getMessage());
client.sayHello({name: user}, function(err, response) {
console.log('Greeting:', response.message);
});
}

@ -31,18 +31,16 @@
*
*/
var grpc = require('grpc');
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var hello_messages = require('./helloworld_pb');
var hello_service = require('./helloworld_grpc_pb');
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
/**
* Implements the SayHello RPC method.
*/
function sayHello(call, callback) {
var reply = new hello_messages.HelloReply();
reply.setMessage("Hello " + call.request.getName());
callback(null, reply);
callback(null, {message: 'Hello ' + call.request.name});
}
/**
@ -51,7 +49,7 @@ function sayHello(call, callback) {
*/
function main() {
var server = new grpc.Server();
server.addService(hello_service.GreeterService, {sayHello: sayHello});
server.addProtoService(hello_proto.Greeter.service, {sayHello: sayHello});
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start();
}

@ -1,39 +0,0 @@
// GENERATED CODE -- DO NOT EDIT!
var grpc = require('grpc');
var helloworld_pb = require('./helloworld_pb.js');
function serialize_HelloReply(arg) {
if (!(arg instanceof helloworld_pb.HelloReply)) {
throw new Error('Expected argument of type HelloReply');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloReply(buffer_arg) {
return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_HelloRequest(arg) {
if (!(arg instanceof helloworld_pb.HelloRequest)) {
throw new Error('Expected argument of type HelloRequest');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloRequest(buffer_arg) {
return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
var GreeterService = exports.GreeterService = {
sayHello: {
path: '/helloworld.Greeter/SayHello',
requestStream: false,
responseStream: false,
requestType: helloworld_pb.HelloRequest,
responseType: helloworld_pb.HelloReply,
requestSerialize: serialize_HelloRequest,
requestDeserialize: deserialize_HelloRequest,
responseSerialize: serialize_HelloReply,
responseDeserialize: deserialize_HelloReply,
},
};
exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService);

@ -1,332 +0,0 @@
/**
* @fileoverview
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
goog.exportSymbol('proto.helloworld.HelloReply', null, global);
goog.exportSymbol('proto.helloworld.HelloRequest', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.helloworld.HelloRequest = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.helloworld.HelloRequest, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.helloworld.HelloRequest.displayName = 'proto.helloworld.HelloRequest';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.helloworld.HelloRequest.prototype.toObject = function(opt_includeInstance) {
return proto.helloworld.HelloRequest.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.helloworld.HelloRequest} msg The msg instance to transform.
* @return {!Object}
*/
proto.helloworld.HelloRequest.toObject = function(includeInstance, msg) {
var f, obj = {
name: msg.getName()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.helloworld.HelloRequest}
*/
proto.helloworld.HelloRequest.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.helloworld.HelloRequest;
return proto.helloworld.HelloRequest.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.helloworld.HelloRequest} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.helloworld.HelloRequest}
*/
proto.helloworld.HelloRequest.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setName(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.helloworld.HelloRequest} message
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloRequest.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.helloworld.HelloRequest.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloRequest.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getName();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.helloworld.HelloRequest} The clone.
*/
proto.helloworld.HelloRequest.prototype.cloneMessage = function() {
return /** @type {!proto.helloworld.HelloRequest} */ (jspb.Message.cloneMessage(this));
};
/**
* optional string name = 1;
* @return {string}
*/
proto.helloworld.HelloRequest.prototype.getName = function() {
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
};
/** @param {string} value */
proto.helloworld.HelloRequest.prototype.setName = function(value) {
jspb.Message.setField(this, 1, value);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.helloworld.HelloReply = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.helloworld.HelloReply, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.helloworld.HelloReply.displayName = 'proto.helloworld.HelloReply';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.helloworld.HelloReply.prototype.toObject = function(opt_includeInstance) {
return proto.helloworld.HelloReply.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.helloworld.HelloReply} msg The msg instance to transform.
* @return {!Object}
*/
proto.helloworld.HelloReply.toObject = function(includeInstance, msg) {
var f, obj = {
message: msg.getMessage()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.helloworld.HelloReply}
*/
proto.helloworld.HelloReply.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.helloworld.HelloReply;
return proto.helloworld.HelloReply.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.helloworld.HelloReply} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.helloworld.HelloReply}
*/
proto.helloworld.HelloReply.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setMessage(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.helloworld.HelloReply} message
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloReply.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.helloworld.HelloReply.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloReply.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getMessage();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.helloworld.HelloReply} The clone.
*/
proto.helloworld.HelloReply.prototype.cloneMessage = function() {
return /** @type {!proto.helloworld.HelloReply} */ (jspb.Message.cloneMessage(this));
};
/**
* optional string message = 1;
* @return {string}
*/
proto.helloworld.HelloReply.prototype.getMessage = function() {
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
};
/** @param {string} value */
proto.helloworld.HelloReply.prototype.setMessage = function(value) {
jspb.Message.setField(this, 1, value);
};
goog.object.extend(exports, proto.helloworld);

@ -4,7 +4,6 @@
"dependencies": {
"async": "^1.5.2",
"grpc": "0.13.0",
"google-protobuf": "*",
"lodash": "^4.6.1",
"minimist": "^1.2.0"
}

@ -281,10 +281,9 @@ class CallOpRecvMessage {
if (message_ == nullptr) return;
if (recv_buf_) {
if (*status) {
got_message = true;
*status = SerializationTraits<R>::Deserialize(recv_buf_, message_,
max_message_size)
.ok();
got_message = *status = SerializationTraits<R>::Deserialize(
recv_buf_, message_, max_message_size)
.ok();
} else {
got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);

@ -268,7 +268,7 @@ static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
if (con != NULL) {
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection");
gpr_atm_no_barrier_store(&c->connected_subchannel, 0xdeadbeef);
gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm)0xdeadbeef);
}
gpr_mu_unlock(&c->mu);
}

@ -629,9 +629,10 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
check_read_ops(exec_ctx, &t->global);
gpr_mu_lock(&t->executor.mu);
if (t->executor.pending_actions != NULL) {
hdr = t->executor.pending_actions;
t->executor.pending_actions = NULL;
if (t->executor.pending_actions_head != NULL) {
hdr = t->executor.pending_actions_head;
t->executor.pending_actions_head = t->executor.pending_actions_tail =
NULL;
gpr_mu_unlock(&t->executor.mu);
while (hdr != NULL) {
hdr->action(exec_ctx, t, hdr->stream, hdr->arg);
@ -686,8 +687,14 @@ void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
gpr_free(hdr);
continue;
}
hdr->next = t->executor.pending_actions;
t->executor.pending_actions = hdr;
hdr->next = NULL;
if (t->executor.pending_actions_head != NULL) {
t->executor.pending_actions_tail =
t->executor.pending_actions_tail->next = hdr;
} else {
t->executor.pending_actions_tail = t->executor.pending_actions_head =
hdr;
}
REF_TRANSPORT(t, "pending_action");
gpr_mu_unlock(&t->executor.mu);
}

@ -236,9 +236,6 @@ struct grpc_chttp2_transport_parsing {
/** was a goaway frame received? */
uint8_t goaway_received;
/** the last sent max_table_size setting */
uint32_t last_sent_max_table_size;
/** initial window change */
int64_t initial_window_update;
@ -272,6 +269,9 @@ struct grpc_chttp2_transport_parsing {
uint32_t incoming_frame_size;
uint32_t incoming_stream_id;
/* current max frame size */
uint32_t max_frame_size;
/* active parser */
void *parser_data;
grpc_chttp2_stream_parsing *incoming_stream;
@ -282,6 +282,8 @@ struct grpc_chttp2_transport_parsing {
/* received settings */
uint32_t settings[GRPC_CHTTP2_NUM_SETTINGS];
/* last settings that were sent */
uint32_t last_sent_settings[GRPC_CHTTP2_NUM_SETTINGS];
/* goaway data */
grpc_status_code goaway_error;
@ -321,7 +323,8 @@ struct grpc_chttp2_transport {
/** is a thread currently parsing */
bool parsing_active;
grpc_chttp2_executor_action_header *pending_actions;
grpc_chttp2_executor_action_header *pending_actions_head;
grpc_chttp2_executor_action_header *pending_actions_tail;
} executor;
/** is the transport destroying itself? */

@ -79,9 +79,12 @@ void grpc_chttp2_prepare_to_read(
GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
transport_parsing->next_stream_id = transport_global->next_stream_id;
transport_parsing->last_sent_max_table_size =
transport_global->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
memcpy(transport_parsing->last_sent_settings,
transport_global->settings[GRPC_SENT_SETTINGS],
sizeof(transport_parsing->last_sent_settings));
transport_parsing->max_frame_size =
transport_global->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
/* update the parsing view of incoming window */
while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
@ -388,6 +391,12 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
return 1;
}
goto dts_fh_0; /* loop */
} else if (transport_parsing->incoming_frame_size >
transport_parsing->max_frame_size) {
gpr_log(GPR_DEBUG, "Frame size %d is larger than max frame size %d",
transport_parsing->incoming_frame_size,
transport_parsing->max_frame_size);
return 0;
}
if (++cur == end) {
return 1;
@ -840,7 +849,11 @@ static int init_settings_frame_parser(
transport_parsing->settings_ack_received = 1;
grpc_chttp2_hptbl_set_max_bytes(
&transport_parsing->hpack_parser.table,
transport_parsing->last_sent_max_table_size);
transport_parsing
->last_sent_settings[GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
transport_parsing->max_frame_size =
transport_parsing
->last_sent_settings[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
}
transport_parsing->parser = grpc_chttp2_settings_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.settings;

@ -47,6 +47,8 @@
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
int grpc_compress_filter_trace = 0;
typedef struct call_data {
gpr_slice_buffer slices; /**< Buffers up input slices to be compressed */
grpc_linked_mdelem compression_algorithm_storage;
@ -169,9 +171,29 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
did_compress =
grpc_msg_compress(calld->compression_algorithm, &calld->slices, &tmp);
if (did_compress) {
if (grpc_compress_filter_trace) {
char *algo_name;
const size_t before_size = calld->slices.length;
const size_t after_size = tmp.length;
const float savings_ratio = 1.0f - (float)after_size / (float)before_size;
GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
&algo_name));
gpr_log(GPR_DEBUG,
"Compressed[%s] %d bytes vs. %d bytes (%.2f%% savings)",
algo_name, before_size, after_size, 100 * savings_ratio);
}
gpr_slice_buffer_swap(&calld->slices, &tmp);
calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
} else {
if (grpc_compress_filter_trace) {
char *algo_name;
GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
&algo_name));
gpr_log(GPR_DEBUG, "Algorithm '%s' enabled but decided not to compress.",
algo_name);
}
}
gpr_slice_buffer_destroy(&tmp);
grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,

@ -38,6 +38,8 @@
#define GRPC_COMPRESS_REQUEST_ALGORITHM_KEY "grpc-internal-encoding-request"
extern int grpc_compress_filter_trace;
/** Compression filter for outgoing data.
*
* See <grpc/compression.h> for the available compression settings.

@ -63,39 +63,45 @@ typedef struct {
grpc_endpoint **endpoint;
} async_connect;
static void async_connect_unlock_and_cleanup(async_connect *ac) {
static void async_connect_unlock_and_cleanup(async_connect *ac,
grpc_winsocket *socket) {
int done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu);
if (done) {
if (ac->socket != NULL) grpc_winsocket_destroy(ac->socket);
gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_name);
gpr_free(ac);
}
if (socket != NULL) grpc_winsocket_destroy(socket);
}
static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool occured) {
async_connect *ac = acp;
gpr_mu_lock(&ac->mu);
/* If the alarm didn't occur, it got cancelled. */
if (ac->socket != NULL && occured) {
if (ac->socket != NULL) {
grpc_winsocket_shutdown(ac->socket);
}
async_connect_unlock_and_cleanup(ac);
async_connect_unlock_and_cleanup(ac, ac->socket);
}
static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, bool from_iocp) {
async_connect *ac = acp;
SOCKET sock = ac->socket->socket;
grpc_endpoint **ep = ac->endpoint;
GPR_ASSERT(*ep == NULL);
grpc_winsocket_callback_info *info = &ac->socket->write_info;
grpc_closure *on_done = ac->on_done;
gpr_mu_lock(&ac->mu);
grpc_winsocket *socket = ac->socket;
ac->socket = NULL;
gpr_mu_unlock(&ac->mu);
grpc_timer_cancel(exec_ctx, &ac->alarm);
gpr_mu_lock(&ac->mu);
if (from_iocp) {
if (from_iocp && socket != NULL) {
DWORD transfered_bytes = 0;
DWORD flags;
BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
@ -107,12 +113,12 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, bool from_iocp) {
ac->addr_name, utf8_message);
gpr_free(utf8_message);
} else {
*ep = grpc_tcp_create(ac->socket, ac->addr_name);
ac->socket = NULL;
*ep = grpc_tcp_create(socket, ac->addr_name);
socket = NULL;
}
}
async_connect_unlock_and_cleanup(ac);
async_connect_unlock_and_cleanup(ac, socket);
/* If the connection was aborted, the callback was already called when
the deadline was met. */
on_done->cb(exec_ctx, on_done->cb_arg, *ep != NULL);
@ -138,6 +144,7 @@ void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
const char *message = NULL;
char *utf8_message;
grpc_winsocket_callback_info *info;
int last_error;
*endpoint = NULL;
@ -208,8 +215,10 @@ void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
return;
failure:
utf8_message = gpr_format_message(WSAGetLastError());
last_error = WSAGetLastError();
utf8_message = gpr_format_message(last_error);
gpr_log(GPR_ERROR, message, utf8_message);
gpr_log(GPR_ERROR, "last error = %d", last_error);
gpr_free(utf8_message);
if (socket != NULL) {
grpc_winsocket_destroy(socket);

@ -164,6 +164,7 @@ void grpc_init(void) {
grpc_register_tracer("channel_stack_builder",
&grpc_trace_channel_stack_builder);
grpc_register_tracer("http1", &grpc_http1_trace);
grpc_register_tracer("compression", &grpc_compress_filter_trace);
grpc_security_pre_init();
grpc_iomgr_init();
grpc_executor_init();

@ -64,28 +64,115 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void AsyncUnary_CompletionSuccess()
public void AsyncUnary_CanBeStartedOnlyOnce()
{
asyncCall.UnaryCallAsync("request1");
Assert.Throws(typeof(InvalidOperationException),
() => asyncCall.UnaryCallAsync("abc"));
}
[Test]
public void AsyncUnary_StreamingOperationsNotAllowed()
{
asyncCall.UnaryCallAsync("request1");
Assert.Throws(typeof(InvalidOperationException),
() => asyncCall.StartReadMessage((x,y) => {}));
Assert.Throws(typeof(InvalidOperationException),
() => asyncCall.StartSendMessage("abc", new WriteFlags(), (x,y) => {}));
}
[Test]
public void AsyncUnary_Success()
{
var resultTask = asyncCall.UnaryCallAsync("request1");
fakeCall.UnaryResponseClientHandler(true,
new ClientSideStatus(Status.DefaultSuccess, new Metadata()),
CreateResponsePayload(),
new Metadata());
AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask);
}
[Test]
public void AsyncUnary_NonSuccessStatusCode()
{
var resultTask = asyncCall.UnaryCallAsync("request1");
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.InvalidArgument),
CreateResponsePayload(),
new Metadata());
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument);
}
[Test]
public void AsyncUnary_NullResponsePayload()
{
var resultTask = asyncCall.UnaryCallAsync("request1");
fakeCall.UnaryResponseClientHandler(true,
new ClientSideStatus(Status.DefaultSuccess, new Metadata()),
null,
new Metadata());
// failure to deserialize will result in InvalidArgument status.
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
}
[Test]
public void ClientStreaming_NoRequest_Success()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
fakeCall.UnaryResponseClientHandler(true,
new ClientSideStatus(Status.DefaultSuccess, new Metadata()),
CreateResponsePayload(),
new Metadata());
AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask);
}
[Test]
public void ClientStreaming_NoRequest_NonSuccessStatusCode()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.InvalidArgument),
CreateResponsePayload(),
new Metadata());
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument);
}
ClientSideStatus CreateClientSideStatus(StatusCode statusCode)
{
return new ClientSideStatus(new Status(statusCode, ""), new Metadata());
}
byte[] CreateResponsePayload()
{
return Marshallers.StringMarshaller.Serializer("response1");
}
static void AssertUnaryResponseSuccess(AsyncCall<string, string> asyncCall, FakeNativeCall fakeCall, Task<string> resultTask)
{
var resultTask = asyncCall.UnaryCallAsync("abc");
fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), new byte[] { 1, 2, 3 }, new Metadata());
Assert.IsTrue(resultTask.IsCompleted);
Assert.IsTrue(fakeCall.IsDisposed);
Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus());
Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count);
Assert.AreEqual(0, asyncCall.GetTrailers().Count);
Assert.AreEqual("response1", resultTask.Result);
}
[Test]
public void AsyncUnary_CompletionFailure()
static void AssertUnaryResponseError(AsyncCall<string, string> asyncCall, FakeNativeCall fakeCall, Task<string> resultTask, StatusCode expectedStatusCode)
{
var resultTask = asyncCall.UnaryCallAsync("abc");
fakeCall.UnaryResponseClientHandler(false, new ClientSideStatus(new Status(StatusCode.Internal, ""), null), new byte[] { 1, 2, 3 }, new Metadata());
Assert.IsTrue(resultTask.IsCompleted);
Assert.IsTrue(fakeCall.IsDisposed);
Assert.AreEqual(StatusCode.Internal, asyncCall.GetStatus().StatusCode);
Assert.IsNull(asyncCall.GetTrailers());
Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode);
var ex = Assert.ThrowsAsync<RpcException>(async () => await resultTask);
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode);
Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count);
Assert.AreEqual(0, asyncCall.GetTrailers().Count);
}
internal class FakeNativeCall : INativeCall

@ -409,10 +409,13 @@ namespace Grpc.Core.Internal
/// </summary>
private void HandleUnaryResponse(bool success, ClientSideStatus receivedStatus, byte[] receivedMessage, Metadata responseHeaders)
{
// NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT,
// success will be always set to true.
using (Profilers.ForCurrentThread().NewScope("AsyncCall.HandleUnaryResponse"))
{
TResponse msg = default(TResponse);
var deserializeException = success ? TryDeserialize(receivedMessage, out msg) : null;
var deserializeException = TryDeserialize(receivedMessage, out msg);
lock (myLock)
{
@ -425,14 +428,13 @@ namespace Grpc.Core.Internal
finishedStatus = receivedStatus;
ReleaseResourcesIfPossible();
}
responseHeadersTcs.SetResult(responseHeaders);
var status = receivedStatus.Status;
if (!success || status.StatusCode != StatusCode.OK)
if (status.StatusCode != StatusCode.OK)
{
unaryResponseTcs.SetException(new RpcException(status));
return;
@ -447,6 +449,9 @@ namespace Grpc.Core.Internal
/// </summary>
private void HandleFinished(bool success, ClientSideStatus receivedStatus)
{
// NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT,
// success will be always set to true.
lock (myLock)
{
finished = true;
@ -457,7 +462,7 @@ namespace Grpc.Core.Internal
var status = receivedStatus.Status;
if (!success || status.StatusCode != StatusCode.OK)
if (status.StatusCode != StatusCode.OK)
{
streamingCallFinishedTcs.SetException(new RpcException(status));
return;

@ -43,7 +43,9 @@
var path = require('path');
var execFile = require('child_process').execFile;
var protoc = path.resolve(__dirname, 'protoc');
var exe_ext = process.platform === 'win32' ? '.exe' : '';
var protoc = path.resolve(__dirname, 'protoc' + exe_ext);
execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
if (error) {

@ -43,9 +43,11 @@
var path = require('path');
var execFile = require('child_process').execFile;
var protoc = path.resolve(__dirname, 'grpc_node_plugin');
var exe_ext = process.platform === 'win32' ? '.exe' : '';
execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext);
execFile(plugin, process.argv.slice(2), function(error, stdout, stderr) {
if (error) {
throw error;
}

@ -136,6 +136,10 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
#pragma mark Finish
- (void)finishWithError:(NSError *)errorOrNil {
@synchronized(self) {
_state = GRXWriterStateFinished;
}
// If the call isn't retained anywhere else, it can be deallocated now.
_retainSelf = nil;
@ -342,6 +346,10 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
#pragma mark GRXWriter implementation
- (void)startWithWriteable:(id<GRXWriteable>)writeable {
@synchronized(self) {
_state = GRXWriterStateStarted;
}
// Create a retain cycle so that this instance lives until the RPC finishes (or is cancelled).
// This makes RPCs in which the call isn't externally retained possible (as long as it is started
// before being autoreleased).
@ -375,30 +383,32 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
}
- (void)setState:(GRXWriterState)newState {
// Manual transitions are only allowed from the started or paused states.
if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) {
return;
}
switch (newState) {
case GRXWriterStateFinished:
_state = newState;
// Per GRXWriter's contract, setting the state to Finished manually
// means one doesn't wish the writeable to be messaged anymore.
[_responseWriteable cancelSilently];
_responseWriteable = nil;
return;
case GRXWriterStatePaused:
_state = newState;
@synchronized(self) {
// Manual transitions are only allowed from the started or paused states.
if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) {
return;
case GRXWriterStateStarted:
if (_state == GRXWriterStatePaused) {
}
switch (newState) {
case GRXWriterStateFinished:
_state = newState;
[self startNextRead];
}
return;
case GRXWriterStateNotStarted:
return;
// Per GRXWriter's contract, setting the state to Finished manually
// means one doesn't wish the writeable to be messaged anymore.
[_responseWriteable cancelSilently];
_responseWriteable = nil;
return;
case GRXWriterStatePaused:
_state = newState;
return;
case GRXWriterStateStarted:
if (_state == GRXWriterStatePaused) {
_state = newState;
[self startNextRead];
}
return;
case GRXWriterStateNotStarted:
return;
}
}
}

@ -272,8 +272,14 @@
XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
[expectation fulfill];
}];
XCTAssertEqual(call.state, GRXWriterStateNotStarted);
[call start];
XCTAssertEqual(call.state, GRXWriterStateStarted);
[call cancel];
XCTAssertEqual(call.state, GRXWriterStateFinished);
[self waitForExpectationsWithTimeout:1 handler:nil];
}

@ -0,0 +1,28 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,132 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Entry point for running stress tests."""
import argparse
import Queue
import threading
from grpc.beta import implementations
from src.proto.grpc.testing import metrics_pb2
from src.proto.grpc.testing import test_pb2
from tests.interop import methods
from tests.qps import histogram
from tests.stress import metrics_server
from tests.stress import test_runner
def _args():
parser = argparse.ArgumentParser(description='gRPC Python stress test client')
parser.add_argument(
'--server_addresses',
help='comma seperated list of hostname:port to run servers on',
default='localhost:8080', type=str)
parser.add_argument(
'--test_cases',
help='comma seperated list of testcase:weighting of tests to run',
default='large_unary:100',
type=str)
parser.add_argument(
'--test_duration_secs',
help='number of seconds to run the stress test',
default=-1, type=int)
parser.add_argument(
'--num_channels_per_server',
help='number of channels per server',
default=1, type=int)
parser.add_argument(
'--num_stubs_per_channel',
help='number of stubs to create per channel',
default=1, type=int)
parser.add_argument(
'--metrics_port',
help='the port to listen for metrics requests on',
default=8081, type=int)
return parser.parse_args()
def _test_case_from_arg(test_case_arg):
for test_case in methods.TestCase:
if test_case_arg == test_case.value:
return test_case
else:
raise ValueError('No test case {}!'.format(test_case_arg))
def _parse_weighted_test_cases(test_case_args):
weighted_test_cases = {}
for test_case_arg in test_case_args.split(','):
name, weight = test_case_arg.split(':', 1)
test_case = _test_case_from_arg(name)
weighted_test_cases[test_case] = int(weight)
return weighted_test_cases
def run_test(args):
test_cases = _parse_weighted_test_cases(args.test_cases)
test_servers = args.server_addresses.split(',')
# Propagate any client exceptions with a queue
exception_queue = Queue.Queue()
stop_event = threading.Event()
hist = histogram.Histogram(1, 1)
runners = []
server = metrics_pb2.beta_create_MetricsService_server(
metrics_server.MetricsServer(hist))
server.add_insecure_port('[::]:{}'.format(args.metrics_port))
server.start()
for test_server in test_servers:
host, port = test_server.split(':', 1)
for _ in xrange(args.num_channels_per_server):
channel = implementations.insecure_channel(host, int(port))
for _ in xrange(args.num_stubs_per_channel):
stub = test_pb2.beta_create_TestService_stub(channel)
runner = test_runner.TestRunner(stub, test_cases, hist,
exception_queue, stop_event)
runners.append(runner)
for runner in runners:
runner.start()
try:
raise exception_queue.get(block=True, timeout=args.test_duration_secs)
except Queue.Empty:
# No exceptions thrown, success
pass
finally:
stop_event.set()
for runner in runners:
runner.join()
runner = None
server.stop(0)
if __name__ == '__main__':
run_test(_args())

@ -0,0 +1,60 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""MetricsService for publishing stress test qps data."""
import time
from src.proto.grpc.testing import metrics_pb2
GAUGE_NAME = 'python_overall_qps'
class MetricsServer(metrics_pb2.BetaMetricsServiceServicer):
def __init__(self, histogram):
self._start_time = time.time()
self._histogram = histogram
def _get_qps(self):
count = self._histogram.get_data().count
delta = time.time() - self._start_time
self._histogram.reset()
self._start_time = time.time()
return int(count/delta)
def GetAllGauges(self, request, context):
qps = self._get_qps()
return [metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)]
def GetGauge(self, request, context):
if request.name != GAUGE_NAME:
raise Exception('Gauge {} does not exist'.format(request.name))
qps = self._get_qps()
return metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)

@ -0,0 +1,73 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Thread that sends random weighted requests on a TestService stub."""
import random
import threading
import time
import traceback
def _weighted_test_case_generator(weighted_cases):
weight_sum = sum(weighted_cases.itervalues())
while True:
val = random.uniform(0, weight_sum)
partial_sum = 0
for case in weighted_cases:
partial_sum += weighted_cases[case]
if val <= partial_sum:
yield case
break
class TestRunner(threading.Thread):
def __init__(self, stub, test_cases, hist, exception_queue, stop_event):
super(TestRunner, self).__init__()
self._exception_queue = exception_queue
self._stop_event = stop_event
self._stub = stub
self._test_cases = _weighted_test_case_generator(test_cases)
self._histogram = hist
def run(self):
while not self._stop_event.is_set():
try:
test_case = next(self._test_cases)
start_time = time.time()
test_case.test_interoperability(self._stub, None)
end_time = time.time()
self._histogram.add((end_time - start_time)*1e9)
except Exception as e:
traceback.print_exc()
self._exception_queue.put(
Exception("An exception occured during test {}"
.format(test_case), e))

@ -60,35 +60,27 @@ grpc_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
grpc_config = ENV['GRPC_CONFIG'] || 'opt'
if ENV.key?('GRPC_LIB_DIR')
grpc_lib_dir = File.join(grpc_root, ENV['GRPC_LIB_DIR'])
else
grpc_lib_dir = File.join(grpc_root, 'libs', grpc_config)
end
ENV['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
unless File.exist?(File.join(grpc_lib_dir, 'libgrpc.a')) or windows
ENV['AR'] = RbConfig::CONFIG['AR'] + ' rcs'
ENV['CC'] = RbConfig::CONFIG['CC']
ENV['LD'] = ENV['CC']
ENV['AR'] = RbConfig::CONFIG['AR'] + ' rcs'
ENV['CC'] = RbConfig::CONFIG['CC']
ENV['LD'] = ENV['CC']
ENV['AR'] = 'libtool -o' if RUBY_PLATFORM =~ /darwin/
ENV['AR'] = 'libtool -o' if RUBY_PLATFORM =~ /darwin/
ENV['EMBED_OPENSSL'] = 'true'
ENV['EMBED_ZLIB'] = 'true'
ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG']
ENV['ARCH_FLAGS'] = '-arch i386 -arch x86_64' if RUBY_PLATFORM =~ /darwin/
ENV['CFLAGS'] = '-DGPR_BACKWARDS_COMPATIBILITY_MODE'
ENV['EMBED_OPENSSL'] = 'true'
ENV['EMBED_ZLIB'] = 'true'
ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG']
ENV['ARCH_FLAGS'] = '-arch i386 -arch x86_64' if RUBY_PLATFORM =~ /darwin/
ENV['CFLAGS'] = '-DGPR_BACKWARDS_COMPATIBILITY_MODE'
output_dir = File.expand_path(RbConfig::CONFIG['topdir'])
grpc_lib_dir = File.join(output_dir, 'libs', grpc_config)
ENV['BUILDDIR'] = output_dir
output_dir = File.expand_path(RbConfig::CONFIG['topdir'])
grpc_lib_dir = File.join(output_dir, 'libs', grpc_config)
ENV['BUILDDIR'] = output_dir
puts 'Building internal gRPC into ' + grpc_lib_dir
system("make -j -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config}")
exit 1 unless $? == 0
end
puts 'Building internal gRPC into ' + grpc_lib_dir
system("make -j -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config}")
exit 1 unless $? == 0
$CFLAGS << ' -I' + File.join(grpc_root, 'include')
$LDFLAGS << ' ' + File.join(grpc_lib_dir, 'libgrpc.a') unless windows

@ -0,0 +1,12 @@
# Ruby gRPC Tools
This package distributes protoc and the Ruby gRPC protoc plugin for Windows, Linux, and Mac.
Before this package is published, the following directories should be filled with the corresponding `protoc` and `grpc_ruby_plugin` executables.
- `bin/x86-linux`
- `bin/x86_64-linux`
- `bin/x86-macos`
- `bin/x86_64-macos`
- `bin/x86-windows`
- `bin/x86_64-windows`

@ -0,0 +1,41 @@
#!/usr/bin/env ruby
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'rbconfig'
require_relative '../os_check'
protoc_name = 'protoc' + RbConfig::CONFIG['EXEEXT']
protoc_path = File.join(File.dirname(__FILE__),
RbConfig::CONFIG['host_cpu'] + '-' + OS.os_name,
protoc_name)
exec([ protoc_path, protoc_path ], *ARGV)

@ -0,0 +1,41 @@
#!/usr/bin/env ruby
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'rbconfig'
require_relative '../os_check'
plugin_name = 'grpc_ruby_plugin' + RbConfig::CONFIG['EXEEXT']
plugin_path = File.join(File.dirname(__FILE__),
RbConfig::CONFIG['host_cpu'] + '-' + OS.os_name,
plugin_name)
exec([ plugin_path, plugin_path ], *ARGV)

@ -0,0 +1,22 @@
# -*- ruby -*-
# encoding: utf-8
require_relative 'version.rb'
Gem::Specification.new do |s|
s.name = 'grpc-tools'
s.version = GRPC::Tools::VERSION
s.authors = ['grpc Authors']
s.email = 'grpc-io@googlegroups.com'
s.homepage = 'https://github.com/google/grpc/tree/master/src/ruby/tools'
s.summary = 'Development tools for Ruby gRPC'
s.description = 'protoc and the Ruby gRPC protoc plugin'
s.license = 'BSD-3-Clause'
s.files = %w( version.rb os_check.rb README.md )
s.files += Dir.glob('bin/**/*')
s.bindir = 'bin'
s.platform = Gem::Platform::RUBY
s.executables = %w( protoc.rb protoc_grpc_ruby_plugin.rb )
end

@ -0,0 +1,45 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# This is based on http://stackoverflow.com/a/171011/159388 by Aaron Hinni
require 'rbconfig'
module OS
def OS.os_name
case RbConfig::CONFIG['host_os']
when /cygwin|mswin|mingw|bccwin|wince|emx/
'windows'
when /darwin/
'macos'
else
'linux'
end
end
end

@ -0,0 +1,34 @@
# 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.
module GRPC
module Tools
VERSION = '0.14.0.dev'
end
end

@ -0,0 +1,36 @@
%YAML 1.2
--- |
# 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.
module GRPC
module Tools
VERSION = '${settings.ruby_version.ruby()}'
end
end

@ -0,0 +1,41 @@
%YAML 1.2
--- |
# 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.
FROM debian:jessie
<%include file="../../apt_get_basic.include"/>
<%include file="../../ccache_setup.include"/>
<%include file="../../cxx_deps.include"/>
<%include file="../../gcp_api_libraries.include"/>
<%include file="../../csharp_deps.include"/>
# Define the default command.
CMD ["bash"]

@ -83,11 +83,15 @@ static void me_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
if (m->parent->shutdown) {
ok = false;
} else if (m->on_read != NULL) {
gpr_slice_buffer_addn(m->on_read_out, slices->slices, slices->count);
for (size_t i = 0; i < slices->count; i++) {
gpr_slice_buffer_add(m->on_read_out, gpr_slice_ref(slices->slices[i]));
}
grpc_exec_ctx_enqueue(exec_ctx, m->on_read, true, NULL);
m->on_read = NULL;
} else {
gpr_slice_buffer_addn(&m->read_buffer, slices->slices, slices->count);
for (size_t i = 0; i < slices->count; i++) {
gpr_slice_buffer_add(&m->read_buffer, gpr_slice_ref(slices->slices[i]));
}
}
gpr_mu_unlock(&m->parent->mu);
grpc_exec_ctx_enqueue(exec_ctx, cb, ok, NULL);

@ -210,7 +210,7 @@ static void install_crash_handler() {
#include <stdio.h>
#include <string.h>
static char g_alt_stack[MINSIGSTKSZ];
static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)];
#define MAX_FRAMES 32

@ -39,6 +39,7 @@
#include <vector>
#include <grpc++/support/byte_buffer.h>
#include <grpc++/support/channel_arguments.h>
#include <grpc++/support/slice.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@ -280,7 +281,7 @@ class ClientImpl : public Client {
create_stub_(create_stub) {
for (int i = 0; i < config.client_channels(); i++) {
channels_[i].init(config.server_targets(i % config.server_targets_size()),
config, create_stub_);
config, create_stub_, i);
}
ClientRequestCreator<RequestType> create_req(&request_,
@ -303,14 +304,17 @@ class ClientImpl : public Client {
}
void init(const grpc::string& target, const ClientConfig& config,
std::function<std::unique_ptr<StubType>(std::shared_ptr<Channel>)>
create_stub) {
create_stub,
int shard) {
// We have to use a 2-phase init like this with a default
// constructor followed by an initializer function to make
// old compilers happy with using this in std::vector
ChannelArguments args;
args.SetInt("shard_to_ensure_no_subchannel_merges", shard);
channel_ = CreateTestChannel(
target, config.security_params().server_host_override(),
config.has_security_params(),
!config.security_params().use_test_ca());
config.has_security_params(), !config.security_params().use_test_ca(),
std::shared_ptr<CallCredentials>(), args);
stub_ = create_stub(channel_);
}
Channel* get_channel() { return channel_.get(); }

@ -83,6 +83,7 @@ static std::unordered_map<string, std::deque<int>> get_hosts_and_cores(
auto stub = WorkerService::NewStub(
CreateChannel(*it, InsecureChannelCredentials()));
grpc::ClientContext ctx;
ctx.set_fail_fast(false);
CoreRequest dummy;
CoreResponse cores;
grpc::Status s = stub->CoreCount(&ctx, dummy, &cores);
@ -166,6 +167,7 @@ namespace runsc {
static ClientContext* AllocContext(list<ClientContext>* contexts) {
contexts->emplace_back();
auto context = &contexts->back();
context->set_fail_fast(false);
return context;
}
@ -435,6 +437,7 @@ void RunQuit() {
CreateChannel(workers[i], InsecureChannelCredentials()));
Void dummy;
grpc::ClientContext ctx;
ctx.set_fail_fast(false);
GPR_ASSERT(stub->QuitWorker(&ctx, dummy, &dummy).ok());
}
}

@ -64,12 +64,13 @@ def headers_under(directory):
def mako_plugin(dictionary):
apis = []
headers = []
# for lib in dictionary['libs']:
# if lib['name'] == 'grpc':
# apis.extend(list_c_apis(lib['public_headers']))
apis.extend(list_c_apis(sorted(headers_under('include/grpc'))))
for lib in dictionary['libs']:
if lib['name'] in ['grpc', 'gpr']:
headers.extend(lib['public_headers'])
apis.extend(list_c_apis(sorted(set(headers))))
dictionary['c_apis'] = apis

@ -0,0 +1,101 @@
# 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.
FROM debian:jessie
# Install Git and basic packages.
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
gcc-multilib \
git \
golang \
gyp \
lcov \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
perl \
strace \
python-dev \
python-setuptools \
python-yaml \
telnet \
unzip \
wget \
zip && apt-get clean
#================
# Build profiling
RUN apt-get update && apt-get install -y time && apt-get clean
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
#=================
# C++ dependencies
RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
# Google Cloud platform API libraries
RUN apt-get update && apt-get install -y python-pip && apt-get clean
RUN pip install --upgrade google-api-python-client
#================
# C# dependencies
# Update to a newer version of mono
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
# Install dependencies
RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \
mono-devel \
ca-certificates-mono \
nuget \
&& apt-get clean
# Define the default command.
CMD ["bash"]

@ -0,0 +1,47 @@
#!/bin/bash
# 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.
#
# Builds C# interop server and client in a base image.
set -e
mkdir -p /var/local/git
git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
# Copy service account keys if available
cp -r /var/local/jenkins/service_account $HOME || true
cd /var/local/git/grpc
# Build C++ metrics client (to query the metrics from csharp stress client)
make metrics_client -j
# Build C# interop client & server
tools/run_tests/run_tests.py -l csharp -c dbg --build_only

@ -32,6 +32,8 @@ set -ex
cd $(dirname $0)/../..
base=$(pwd)
mkdir -p artifacts/
# All the ruby packages have been built in the artifact phase already
@ -41,3 +43,25 @@ cp -r $EXTERNAL_GIT_ROOT/architecture={x86,x64},language=ruby,platform={windows,
# TODO: all the artifact builder configurations generate a grpc-VERSION.gem
# source distribution package, and only one of them will end up
# in the artifacts/ directory. They should be all equivalent though.
for arch in {x86,x64}; do
case $arch in
x64)
ruby_arch=x86_64
;;
*)
ruby_arch=$arch
;;
esac
for plat in {windows,linux,macos}; do
input_dir="$EXTERNAL_GIT_ROOT/architecture=$arch,language=protoc,platform=$plat/artifacts"
output_dir="$base/src/ruby/tools/bin/${ruby_arch}-${plat}"
mkdir -p $output_dir
cp $input_dir/protoc* $output_dir/
cp $input_dir/grpc_ruby_plugin* $output_dir/
done
done
cd $base/src/ruby/tools
gem build grpc-tools.gemspec
cp ./grpc-tools*.gem $base/artifacts/

@ -47,5 +47,8 @@ ps -C ruby -o pid=,cmd= | grep 'qps/worker.rb' | awk '{print $1}' | xargs kill -
# Node
ps -C node -o pid=,cmd= | grep 'performance/worker.js' | awk '{print $1}' | xargs kill -9
# Python
ps -C python -o pid=,cmd= | grep 'qps_worker.py' | awk '{print $1}' | xargs kill -9
# Java
jps | grep LoadWorker | awk '{print $1}' | xargs kill -9

@ -0,0 +1,90 @@
{
"dockerImages": {
"grpc_stress_csharp" : {
"buildScript": "tools/jenkins/build_interop_stress_image.sh",
"dockerFileDir": "grpc_interop_stress_csharp"
}
},
"clientTemplates": {
"baseTemplates": {
"default": {
"wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py",
"pollIntervalSecs": 60,
"clientArgs": {
"num_channels_per_server":5,
"num_stubs_per_channel":10,
"test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1",
"metrics_port": 8081
},
"metricsPort": 8081,
"metricsArgs": {
"metrics_server_address": "localhost:8081",
"total_only": "true"
}
}
},
"templates": {
"csharp_client": {
"baseTemplate": "default",
"stressClientCmd": [
"mono",
"/var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.StressClient/bin/Debug/Grpc.IntegrationTesting.StressClient.exe"
],
"metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"]
}
}
},
"serverTemplates": {
"baseTemplates":{
"default": {
"wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py",
"serverPort": 8080,
"serverArgs": {
"port": 8080
}
}
},
"templates": {
"csharp_server": {
"baseTemplate": "default",
"stressServerCmd": [
"mono",
"/var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Server/bin/Debug/Grpc.IntegrationTesting.Server.exe"
]
}
}
},
"testMatrix": {
"serverPodSpecs": {
"stress-server-csharp": {
"serverTemplate": "csharp_server",
"dockerImage": "grpc_stress_csharp",
"numInstances": 1
}
},
"clientPodSpecs": {
"stress-client-csharp": {
"clientTemplate": "csharp_client",
"dockerImage": "grpc_stress_csharp",
"numInstances": 10,
"serverPodSpec": "stress-server-csharp"
}
}
},
"globalSettings": {
"buildDockerImages": true,
"pollIntervalSecs": 60,
"testDurationSecs": 7200,
"kubernetesProxyPort": 8001,
"datasetIdNamePrefix": "stress_test_csharp",
"summaryTableId": "summary",
"qpsTableId": "qps",
"podWarmupSecs": 60
}
}

@ -57757,6 +57757,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/03a72675e1969f836094f1ecfec2a7b34418e306"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/03b9be1fa172dff5d1543be079b9c64fa2c9a278"
@ -57773,6 +57789,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/0416afd6875d9ba55f1e5f86a6456a5445d5e576"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/052c8f28e5884bb48f0d504461272cd3a5893215"
@ -57917,6 +57949,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/08c42ef29eff83052c5887855f2fa3e07ebe470c"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/09938e3256d06a8e168eb038d8a58b8462f7f697"
@ -58365,6 +58413,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/1ba889ea1543297824e99e641e6ca8b91f45732e"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/1cf17783de9e662f3720847f2d83d86dcdcab500"
@ -59149,6 +59213,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/3b09bf453c6f93983c24c4d5481e55d66213f93a"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/3ca5da2f.bin"
@ -59501,6 +59581,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/49cb33cbb60f041e8e99dd718993acd2c3354416"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/4aa883d0.bin"
@ -59949,6 +60045,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/59743fe120be6ae1aed1c02230ee1bb460f621ee"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/597fdab5.bin"
@ -61341,6 +61453,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/a5ccb8f124d8ddb5350b90bc0d6b96db280cb7c9"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/a7e64803.bin"
@ -61357,6 +61485,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/a7fac1265a384fe9e45a9ee3d708b79c4e80505e"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/a8d229374635fa6f2a75ca1669892e1bc244e719"
@ -61501,6 +61645,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/aaf049720c707d4e14e47e7eb31d6a2dda60e66a"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/ad810f7f.bin"
@ -61965,6 +62125,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/c4e4c7572e005e18d56eac407033da058737a5ab"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/c559f565.bin"
@ -62269,6 +62445,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/crash-dae0f07934a527989f23f06e630710ff6ca8c809"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/crash-e34b0a9a428001cb4094a9ebca76329f578811a4"
@ -62589,6 +62781,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/e96ad9c17795e52edc810a08d4fc61fe8790002a"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/e9bbe2fe47b7b9c2683e7f17f4a33625c6ffbd8c"
@ -62909,6 +63117,22 @@
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/fa202a5f51cd49f8ea5af60c5f403f797c01c504"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
]
},
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/fa36b4280d9e28edd81c5e4d192d1a5c2765e5e4"

Loading…
Cancel
Save