Merge branch 'tis-but-thy-name' into just-say-goodbye-when-we-are-done

pull/2304/head^2
Craig Tiller 10 years ago
commit be3da35369
  1. 36
      Makefile
  2. 3
      build.json
  3. 4
      gRPC.podspec
  4. 4
      include/grpc/byte_buffer.h
  5. 16
      src/core/client_config/README.md
  6. 4
      src/core/client_config/lb_policies/pick_first.c
  7. 5
      src/core/iomgr/fd_posix.c
  8. 8
      src/core/iomgr/pollset_multipoller_with_epoll.c
  9. 3
      src/core/iomgr/pollset_posix.c
  10. 5
      src/core/security/server_secure_chttp2.c
  11. 14
      src/core/surface/byte_buffer.c
  12. 3
      src/core/surface/channel_create.c
  13. 6
      src/core/surface/secure_channel_create.c
  14. 3
      src/core/surface/server_chttp2.c
  15. 1
      src/core/transport/chttp2/incoming_metadata.c
  16. 3
      src/core/transport/chttp2/parsing.c
  17. 21
      src/core/transport/chttp2_transport.c
  18. 7
      src/core/transport/chttp2_transport.h
  19. 4
      src/objective-c/GRPCClient/GRPCCall.h
  20. 10
      src/objective-c/GRPCClient/GRPCCall.m
  21. 40
      src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h
  22. 44
      src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m
  23. 2
      src/objective-c/GRPCClient/private/GRPCWrappedCall.h
  24. 8
      src/objective-c/GRPCClient/private/GRPCWrappedCall.m
  25. 17
      src/objective-c/ProtoRPC/ProtoMethod.h
  26. 16
      src/objective-c/ProtoRPC/ProtoMethod.m
  27. 4
      src/objective-c/ProtoRPC/ProtoRPC.h
  28. 17
      src/objective-c/ProtoRPC/ProtoRPC.m
  29. 6
      src/objective-c/ProtoRPC/ProtoService.m
  30. 28
      src/objective-c/tests/GRPCClientTests.m
  31. 14
      src/objective-c/tests/LocalClearTextTests.m
  32. 2
      src/ruby/ext/grpc/extconf.rb
  33. 4
      templates/gRPC.podspec.template
  34. 3
      test/core/bad_client/bad_client.c
  35. 8
      test/core/end2end/fixtures/chttp2_socket_pair.c
  36. 8
      test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c
  37. 8
      test/core/end2end/fixtures/chttp2_socket_pair_with_grpc_trace.c
  38. 25
      test/core/surface/byte_buffer_reader_test.c
  39. 71
      test/cpp/qps/perf_db.proto
  40. 143
      test/cpp/qps/perf_db_client.cc
  41. 115
      test/cpp/qps/perf_db_client.h
  42. 70
      test/cpp/qps/report.cc
  43. 30
      test/cpp/qps/report.h
  44. 33
      test/cpp/qps/server_async.cc
  45. 18
      test/cpp/util/benchmark_config.cc
  46. 5
      tools/run_tests/sources_and_headers.json

@ -2674,6 +2674,21 @@ $(GENDIR)/examples/pubsub/pubsub.grpc.pb.cc: examples/pubsub/pubsub.proto $(PROT
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
$(GENDIR)/test/cpp/qps/perf_db.pb.cc: protoc_dep_error
$(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc: protoc_dep_error
else
$(GENDIR)/test/cpp/qps/perf_db.pb.cc: test/cpp/qps/perf_db.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc: test/cpp/qps/perf_db.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
$(GENDIR)/test/cpp/qps/qpstest.pb.cc: protoc_dep_error
$(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc: protoc_dep_error
@ -4244,9 +4259,11 @@ $(OBJDIR)/$(CONFIG)/examples/pubsub/subscriber.o: $(GENDIR)/examples/pubsub/labe
LIBQPS_SRC = \
$(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc \
$(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc \
test/cpp/qps/client_async.cc \
test/cpp/qps/client_sync.cc \
test/cpp/qps/driver.cc \
test/cpp/qps/perf_db_client.cc \
test/cpp/qps/qps_worker.cc \
test/cpp/qps/report.cc \
test/cpp/qps/server_async.cc \
@ -4296,15 +4313,16 @@ ifneq ($(NO_DEPS),true)
-include $(LIBQPS_OBJS:.o=.dep)
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/timer.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/util/benchmark_config.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/perf_db_client.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/qps/timer.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/util/benchmark_config.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
LIBGRPC_CSHARP_EXT_SRC = \

@ -768,6 +768,7 @@
"test/cpp/qps/driver.h",
"test/cpp/qps/histogram.h",
"test/cpp/qps/interarrival.h",
"test/cpp/qps/perf_db_client.h",
"test/cpp/qps/qps_worker.h",
"test/cpp/qps/report.h",
"test/cpp/qps/server.h",
@ -777,9 +778,11 @@
],
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/perf_db.proto",
"test/cpp/qps/client_async.cc",
"test/cpp/qps/client_sync.cc",
"test/cpp/qps/driver.cc",
"test/cpp/qps/perf_db_client.cc",
"test/cpp/qps/qps_worker.cc",
"test/cpp/qps/report.cc",
"test/cpp/qps/server_async.cc",

@ -524,9 +524,9 @@ Pod::Spec.new do |s|
BAD_TIME="$DIR_TIME/time.h"
GOOD_TIME="$DIR_TIME/grpc_time.h"
grep -rl "$BAD_TIME" grpc src/core src/objective-c/GRPCClient | xargs sed -i '' -e s@$BAD_TIME@$GOOD_TIME@g
if [ -f "include/$BAD_TIME" ];
if [ -f "$BAD_TIME" ];
then
mv -f "include/$BAD_TIME" "include/$GOOD_TIME"
mv -f "$BAD_TIME" "$GOOD_TIME"
fi
DIR_STRING="src/core/support"

@ -102,6 +102,10 @@ void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader);
int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
gpr_slice *slice);
/** Returns a RAW byte buffer instance from the output of \a reader. */
grpc_byte_buffer *grpc_raw_byte_buffer_from_reader(
grpc_byte_buffer_reader *reader);
#ifdef __cplusplus
}
#endif

@ -42,3 +42,19 @@ Their behavior is specified by a set of grpc channel filters defined at their
construction. To customize this behavior, resolvers build grpc_subchannel_factory
objects, which use the decorator pattern to customize construction arguments for
concrete grpc_subchannel instances.
Naming for GRPC
===============
Names in GRPC are represented by a URI.
The following schemes are currently supported:
dns:///host:port - dns schemes are currently supported so long as authority is
empty (authority based dns resolution is expected in a future
release)
unix:path - the unix scheme is used to create and connect to unix domain
sockets - the authority must be empty, and the path represents
the absolute or relative path to the desired socket

@ -155,8 +155,6 @@ loop:
switch (p->checking_connectivity) {
case GRPC_CHANNEL_READY:
p->selected = p->subchannels[p->checking_subchannel];
GPR_ASSERT(grpc_subchannel_check_connectivity(p->selected) ==
GRPC_CHANNEL_READY);
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = p->selected;
@ -185,6 +183,7 @@ loop:
GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
p->subchannels[p->num_subchannels - 1]);
p->num_subchannels--;
GRPC_SUBCHANNEL_UNREF(p->subchannels[p->num_subchannels], "pick_first");
if (p->num_subchannels == 0) {
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
@ -197,7 +196,6 @@ loop:
p->checking_subchannel %= p->num_subchannels;
p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]);
GRPC_SUBCHANNEL_UNREF(p->subchannels[p->num_subchannels], "pick_first");
add_interested_parties_locked(p);
goto loop;
}

@ -369,16 +369,17 @@ gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
watcher->fd = NULL;
watcher->pollset = NULL;
gpr_mu_unlock(&fd->watcher_mu);
GRPC_FD_UNREF(fd, "poll");
return 0;
}
/* if there is nobody polling for read, but we need to, then start doing so */
if (!fd->read_watcher && gpr_atm_acq_load(&fd->readst) > READY) {
if (read_mask && !fd->read_watcher && gpr_atm_acq_load(&fd->readst) > READY) {
fd->read_watcher = watcher;
mask |= read_mask;
}
/* if there is nobody polling for write, but we need to, then start doing so
*/
if (!fd->write_watcher && gpr_atm_acq_load(&fd->writest) > READY) {
if (write_mask && !fd->write_watcher && gpr_atm_acq_load(&fd->writest) > READY) {
fd->write_watcher = watcher;
mask |= write_mask;
}

@ -54,7 +54,13 @@ static void multipoll_with_epoll_pollset_add_fd(grpc_pollset *pollset,
pollset_hdr *h = pollset->data.ptr;
struct epoll_event ev;
int err;
grpc_fd_watcher watcher;
/* We pretend to be polling whilst adding an fd to keep the fd from being
closed during the add. This may result in a spurious wakeup being assigned
to this pollset whilst adding, but that should be benign. */
GPR_ASSERT(grpc_fd_begin_poll(fd, pollset, 0, 0, &watcher) == 0);
if (watcher.fd != NULL) {
ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
ev.data.ptr = fd;
err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD, fd->fd, &ev);
@ -65,6 +71,8 @@ static void multipoll_with_epoll_pollset_add_fd(grpc_pollset *pollset,
strerror(errno));
}
}
}
grpc_fd_end_poll(&watcher, 0, 0);
}
static void multipoll_with_epoll_pollset_del_fd(grpc_pollset *pollset,

@ -249,7 +249,8 @@ static void basic_do_promote(void *args, int success) {
pollset->in_flight_cbs--;
if (pollset->shutting_down) {
/* We don't care about this pollset anymore. */
if (pollset->in_flight_cbs == 0 && pollset->counter == 0) {
if (pollset->in_flight_cbs == 0 && pollset->counter == 0 && !pollset->called_shutdown) {
pollset->called_shutdown = 1;
do_shutdown_cb = 1;
}
} else if (grpc_fd_is_orphaned(fd)) {

@ -99,9 +99,10 @@ static void on_secure_transport_setup_done(void *statep,
if (!state->is_shutdown) {
mdctx = grpc_mdctx_create();
transport = grpc_create_chttp2_transport(
grpc_server_get_channel_args(state->server), secure_endpoint, NULL, 0,
mdctx, 0);
grpc_server_get_channel_args(state->server), secure_endpoint, mdctx,
0);
setup_transport(state, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
} else {
/* We need to consume this here, because the server may already have gone
* away. */

@ -55,6 +55,20 @@ grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create(
return bb;
}
grpc_byte_buffer *grpc_raw_byte_buffer_from_reader(
grpc_byte_buffer_reader *reader) {
grpc_byte_buffer *bb = malloc(sizeof(grpc_byte_buffer));
gpr_slice slice;
bb->type = GRPC_BB_RAW;
bb->data.raw.compression = GRPC_COMPRESS_NONE;
gpr_slice_buffer_init(&bb->data.raw.slice_buffer);
while (grpc_byte_buffer_reader_next(reader, &slice)) {
gpr_slice_buffer_add(&bb->data.raw.slice_buffer, slice);
}
return bb;
}
grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb) {
switch (bb->type) {
case GRPC_BB_RAW:

@ -72,7 +72,8 @@ static void connected(void *arg, grpc_endpoint *tcp) {
grpc_iomgr_closure *notify;
if (tcp != NULL) {
c->result->transport = grpc_create_chttp2_transport(
c->args.channel_args, tcp, NULL, 0, c->args.metadata_context, 1);
c->args.channel_args, tcp, c->args.metadata_context, 1);
grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0);
GPR_ASSERT(c->result->transport);
c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *));
c->result->filters[0] = &grpc_http_client_filter;

@ -82,9 +82,9 @@ static void on_secure_transport_setup_done(void *arg,
gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
memset(c->result, 0, sizeof(*c->result));
} else {
c->result->transport =
grpc_create_chttp2_transport(c->args.channel_args, secure_endpoint,
NULL, 0, c->args.metadata_context, 1);
c->result->transport = grpc_create_chttp2_transport(
c->args.channel_args, secure_endpoint, c->args.metadata_context, 1);
grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0);
c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *) * 2);
c->result->filters[0] = &grpc_client_auth_filter;
c->result->filters[1] = &grpc_http_client_filter;

@ -61,8 +61,9 @@ static void new_transport(void *server, grpc_endpoint *tcp) {
*/
grpc_mdctx *mdctx = grpc_mdctx_create();
grpc_transport *transport = grpc_create_chttp2_transport(
grpc_server_get_channel_args(server), tcp, NULL, 0, mdctx, 0);
grpc_server_get_channel_args(server), tcp, mdctx, 0);
setup_transport(server, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
}
/* Server callback: start listening on our ports */

@ -124,6 +124,7 @@ void grpc_incoming_metadata_buffer_move_to_referencing_sopb(
sopb->ops[i].data.metadata.list.tail =
(void *)(delta + (gpr_intptr)sopb->ops[i].data.metadata.list.tail);
}
src->count = 0;
}
void grpc_chttp2_incoming_metadata_buffer_postprocess_sopb_and_begin_live_op(

@ -109,9 +109,6 @@ void grpc_chttp2_publish_reads(
transport_parsing->incoming_stream_id;
}
/* TODO(ctiller): re-implement */
GPR_ASSERT(transport_parsing->initial_window_update == 0);
/* copy parsing qbuf to global qbuf */
gpr_slice_buffer_move_into(&transport_parsing->qbuf, &transport_global->qbuf);

@ -201,8 +201,8 @@ static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
static void init_transport(grpc_chttp2_transport *t,
const grpc_channel_args *channel_args,
grpc_endpoint *ep, gpr_slice *slices, size_t nslices,
grpc_mdctx *mdctx, int is_client) {
grpc_endpoint *ep, grpc_mdctx *mdctx,
int is_client) {
size_t i;
int j;
@ -311,9 +311,6 @@ static void init_transport(grpc_chttp2_transport *t,
}
}
}
REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */
recv_data(t, slices, nslices, GRPC_ENDPOINT_CB_OK);
}
static void destroy_transport(grpc_transport *gt) {
@ -942,6 +939,7 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices,
if (t->parsing.initial_window_update != 0) {
grpc_chttp2_stream_map_for_each(&t->parsing_stream_map,
update_global_window, t);
t->parsing.initial_window_update = 0;
}
/* handle higher level things */
grpc_chttp2_publish_reads(&t->global, &t->parsing);
@ -1051,9 +1049,16 @@ static const grpc_transport_vtable vtable = {
perform_transport_op, destroy_stream, destroy_transport};
grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep, gpr_slice *slices,
size_t nslices, grpc_mdctx *mdctx, int is_client) {
const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx,
int is_client) {
grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
init_transport(t, channel_args, ep, slices, nslices, mdctx, is_client);
init_transport(t, channel_args, ep, mdctx, is_client);
return &t->base;
}
void grpc_chttp2_transport_start_reading(grpc_transport *transport,
gpr_slice *slices, size_t nslices) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */
recv_data(t, slices, nslices, GRPC_ENDPOINT_CB_OK);
}

@ -41,7 +41,10 @@ extern int grpc_http_trace;
extern int grpc_flowctl_trace;
grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep, gpr_slice *slices,
size_t nslices, grpc_mdctx *metadata_context, int is_client);
const grpc_channel_args *channel_args, grpc_endpoint *ep,
grpc_mdctx *metadata_context, int is_client);
void grpc_chttp2_transport_start_reading(grpc_transport *transport,
gpr_slice *slices, size_t nslices);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_TRANSPORT_H */

@ -48,8 +48,6 @@
#import <Foundation/Foundation.h>
#import <RxLibrary/GRXWriter.h>
@class GRPCMethodName;
// Key used in |NSError|'s |userInfo| dictionary to store the response metadata sent by the server.
extern id const kGRPCStatusMetadataKey;
@ -90,7 +88,7 @@ extern id const kGRPCStatusMetadataKey;
// the specific remote method called).
// To finish a call right away, invoke cancel.
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
path:(NSString *)path
requestsWriter:(id<GRXWriter>)requestsWriter NS_DESIGNATED_INITIALIZER;
// Finishes the request side of this call, notifies the server that the RPC

@ -36,11 +36,9 @@
#include <grpc/grpc.h>
#include <grpc/support/time.h>
#import "GRPCMethodName.h"
#import "private/GRPCChannel.h"
#import "private/GRPCCompletionQueue.h"
#import "private/GRPCDelegateWrapper.h"
#import "private/GRPCMethodName+HTTP2Encoding.h"
#import "private/GRPCWrappedCall.h"
#import "private/NSData+GRPC.h"
#import "private/NSDictionary+GRPC.h"
@ -90,14 +88,14 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
@synthesize state = _state;
- (instancetype)init {
return [self initWithHost:nil method:nil requestsWriter:nil];
return [self initWithHost:nil path:nil requestsWriter:nil];
}
// Designated initializer
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
path:(NSString *)path
requestsWriter:(id<GRXWriter>)requestWriter {
if (!host || !method) {
if (!host || !path) {
[NSException raise:NSInvalidArgumentException format:@"Neither host nor method can be nil."];
}
if (requestWriter.state != GRXWriterStateNotStarted) {
@ -114,7 +112,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
_channel = [GRPCChannel channelToHost:host];
_wrappedCall = [[GRPCWrappedCall alloc] initWithChannel:_channel
method:method.HTTP2Path
path:path
host:host];
// Serial queue to invoke the non-reentrant methods of the grpc_call object.

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

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

@ -84,7 +84,7 @@
@interface GRPCWrappedCall : NSObject
- (instancetype)initWithChannel:(GRPCChannel *)channel
method:(NSString *)method
path:(NSString *)path
host:(NSString *)host NS_DESIGNATED_INITIALIZER;
- (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void(^)())errorHandler;

@ -225,13 +225,13 @@
}
- (instancetype)init {
return [self initWithChannel:nil method:nil host:nil];
return [self initWithChannel:nil path:nil host:nil];
}
- (instancetype)initWithChannel:(GRPCChannel *)channel
method:(NSString *)method
path:(NSString *)path
host:(NSString *)host {
if (!channel || !method || !host) {
if (!channel || !path || !host) {
[NSException raise:NSInvalidArgumentException
format:@"channel, method, and host cannot be nil."];
}
@ -247,7 +247,7 @@
return nil;
}
_call = grpc_channel_create_call(channel.unmanagedChannel, _queue.unmanagedQueue,
method.UTF8String, host.UTF8String, gpr_inf_future);
path.UTF8String, host.UTF8String, gpr_inf_future);
if (_call == NULL) {
return nil;
}

@ -33,17 +33,16 @@
#import <Foundation/Foundation.h>
// See the README file for an introduction to this library.
// A fully-qualified gRPC method name. Full qualification is needed because a gRPC endpoint can
// implement multiple interfaces.
// TODO(jcanizales): Move to ProtoRPC package.
// TODO(jcanizales): Rename interface -> service.
@interface GRPCMethodName : NSObject
// A fully-qualified proto service method name. Full qualification is needed because a gRPC endpoint
// can implement multiple services.
@interface ProtoMethod : NSObject
@property(nonatomic, readonly) NSString *package;
@property(nonatomic, readonly) NSString *interface;
@property(nonatomic, readonly) NSString *service;
@property(nonatomic, readonly) NSString *method;
@property(nonatomic, readonly) NSString *HTTPPath;
- (instancetype)initWithPackage:(NSString *)package
interface:(NSString *)interface
service:(NSString *)service
method:(NSString *)method;
@end

@ -31,17 +31,25 @@
*
*/
#import "GRPCMethodName.h"
#import "ProtoMethod.h"
@implementation GRPCMethodName
@implementation ProtoMethod
- (instancetype)initWithPackage:(NSString *)package
interface:(NSString *)interface
service:(NSString *)service
method:(NSString *)method {
if ((self = [super init])) {
_package = [package copy];
_interface = [interface copy];
_service = [service copy];
_method = [method copy];
}
return self;
}
- (NSString *)HTTPPath {
if (_package) {
return [NSString stringWithFormat:@"/%@.%@/%@", _package, _service, _method];
} else {
return [NSString stringWithFormat:@"/%@/%@", _service, _method];
}
}
@end

@ -34,10 +34,12 @@
#import <Foundation/Foundation.h>
#import <GRPCClient/GRPCCall.h>
#import "ProtoMethod.h"
@interface ProtoRPC : GRPCCall
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
method:(ProtoMethod *)method
requestsWriter:(id<GRXWriter>)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable NS_DESIGNATED_INITIALIZER;

@ -42,19 +42,20 @@
id<GRXWriteable> _responseWriteable;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
path:(NSString *)path
requestsWriter:(id<GRXWriter>)requestsWriter {
return [self initWithHost:host
method:method
requestsWriter:requestsWriter
responseClass:nil
responsesWriteable:nil];
[NSException raise:NSInvalidArgumentException
format:@"Please use ProtoRPC's designated initializer instead."];
return nil;
}
#pragma clang diagnostic pop
// Designated initializer
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
method:(ProtoMethod *)method
requestsWriter:(id<GRXWriter>)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable {
@ -70,7 +71,7 @@
// sending GPBMessages.
return [proto data];
}];
if ((self = [super initWithHost:host method:method requestsWriter:bytesWriter])) {
if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) {
// A writeable that parses the proto messages received.
_responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
[responsesWriteable writeValue:[responseClass parseFromData:value error:NULL]];

@ -33,10 +33,10 @@
#import "ProtoService.h"
#import <GRPCClient/GRPCMethodName.h>
#import <RxLibrary/GRXWriteable.h>
#import <RxLibrary/GRXWriter.h>
#import "ProtoMethod.h"
#import "ProtoRPC.h"
@implementation ProtoService {
@ -69,8 +69,8 @@
requestsWriter:(id<GRXWriter>)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable {
GRPCMethodName *methodName = [[GRPCMethodName alloc] initWithPackage:_packageName
interface:_serviceName
ProtoMethod *methodName = [[ProtoMethod alloc] initWithPackage:_packageName
service:_serviceName
method:method];
return [[ProtoRPC alloc] initWithHost:_host
method:methodName

@ -35,7 +35,7 @@
#import <XCTest/XCTest.h>
#import <GRPCClient/GRPCCall.h>
#import <GRPCClient/GRPCMethodName.h>
#import <ProtoRPC/ProtoMethod.h>
#import <RemoteTest/Messages.pbobjc.h>
#import <RxLibrary/GRXWriteable.h>
#import <RxLibrary/GRXWriter+Immediate.h>
@ -47,9 +47,9 @@ static NSString * const kHostAddress = @"grpc-test.sandbox.google.com";
static NSString * const kPackage = @"grpc.testing";
static NSString * const kService = @"TestService";
static GRPCMethodName *kInexistentMethod;
static GRPCMethodName *kEmptyCallMethod;
static GRPCMethodName *kUnaryCallMethod;
static ProtoMethod *kInexistentMethod;
static ProtoMethod *kEmptyCallMethod;
static ProtoMethod *kUnaryCallMethod;
@interface GRPCClientTests : XCTestCase
@end
@ -58,14 +58,14 @@ static GRPCMethodName *kUnaryCallMethod;
- (void)setUp {
// This method isn't implemented by the remote server.
kInexistentMethod = [[GRPCMethodName alloc] initWithPackage:kPackage
interface:kService
kInexistentMethod = [[ProtoMethod alloc] initWithPackage:kPackage
service:kService
method:@"Inexistent"];
kEmptyCallMethod = [[GRPCMethodName alloc] initWithPackage:kPackage
interface:kService
kEmptyCallMethod = [[ProtoMethod alloc] initWithPackage:kPackage
service:kService
method:@"EmptyCall"];
kUnaryCallMethod = [[GRPCMethodName alloc] initWithPackage:kPackage
interface:kService
kUnaryCallMethod = [[ProtoMethod alloc] initWithPackage:kPackage
service:kService
method:@"UnaryCall"];
}
@ -73,7 +73,7 @@ static GRPCMethodName *kUnaryCallMethod;
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
method:kInexistentMethod
path:kInexistentMethod.HTTPPath
requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
@ -95,7 +95,7 @@ static GRPCMethodName *kUnaryCallMethod;
__weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
method:kEmptyCallMethod
path:kEmptyCallMethod.HTTPPath
requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
@ -123,7 +123,7 @@ static GRPCMethodName *kUnaryCallMethod;
id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
method:kUnaryCallMethod
path:kUnaryCallMethod.HTTPPath
requestsWriter:requestsWriter];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
@ -153,7 +153,7 @@ static GRPCMethodName *kUnaryCallMethod;
id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
method:kUnaryCallMethod
path:kUnaryCallMethod.HTTPPath
requestsWriter:requestsWriter];
call.requestMetadata[@"Authorization"] = @"Bearer bogusToken";

@ -35,7 +35,7 @@
#import <XCTest/XCTest.h>
#import <GRPCClient/GRPCCall.h>
#import <GRPCClient/GRPCMethodName.h>
#import <ProtoRPC/ProtoMethod.h>
#import <RouteGuide/RouteGuide.pbobjc.h>
#import <RouteGuide/RouteGuide.pbrpc.h>
#import <RxLibrary/GRXWriteable.h>
@ -87,14 +87,14 @@ static NSString * const kService = @"RouteGuide";
__weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
__weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:kPackage
interface:kService
ProtoMethod *method = [[ProtoMethod alloc] initWithPackage:kPackage
service:kService
method:@"RecordRoute"];
id<GRXWriter> requestsWriter = [GRXWriter emptyWriter];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
method:method
path:method.HTTPPath
requestsWriter:requestsWriter];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
@ -115,8 +115,8 @@ static NSString * const kService = @"RouteGuide";
__weak XCTestExpectation *response = [self expectationWithDescription:@"Response received."];
__weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."];
GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:kPackage
interface:kService
ProtoMethod *method = [[ProtoMethod alloc] initWithPackage:kPackage
service:kService
method:@"GetFeature"];
RGDPoint *point = [RGDPoint message];
@ -125,7 +125,7 @@ static NSString * const kService = @"RouteGuide";
id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[point data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
method:method
path:method.HTTPPath
requestsWriter:requestsWriter];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {

@ -89,7 +89,7 @@ $CFLAGS << ' -Wno-return-type '
$CFLAGS << ' -Wall '
$CFLAGS << ' -pedantic '
$LDFLAGS << ' -lgrpc -lgpr -ldl'
$LDFLAGS << ' -lgrpc -lgpr -lz -ldl'
crash('need grpc lib') unless have_library('grpc', 'grpc_channel_destroy')
have_library('grpc', 'grpc_channel_destroy')

@ -111,9 +111,9 @@ Pod::Spec.new do |s|
BAD_TIME="$DIR_TIME/time.h"
GOOD_TIME="$DIR_TIME/grpc_time.h"
grep -rl "$BAD_TIME" grpc src/core src/objective-c/GRPCClient | xargs sed -i '' -e s@$BAD_TIME@$GOOD_TIME@g
if [ -f "include/$BAD_TIME" ];
if [ -f "$BAD_TIME" ];
then
mv -f "include/$BAD_TIME" "include/$GOOD_TIME"
mv -f "$BAD_TIME" "$GOOD_TIME"
fi
DIR_STRING="src/core/support"

@ -108,8 +108,9 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator,
a.validator = validator;
grpc_server_register_completion_queue(a.server, a.cq);
grpc_server_start(a.server);
transport = grpc_create_chttp2_transport(NULL, sfd.server, NULL, 0, mdctx, 0);
transport = grpc_create_chttp2_transport(NULL, sfd.server, mdctx, 0);
server_setup_transport(&a, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
/* Bind everything into the same pollset */
grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(a.cq));

@ -108,10 +108,10 @@ static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f,
sp_client_setup cs;
cs.client_args = client_args;
cs.f = f;
transport =
grpc_create_chttp2_transport(client_args, sfd->client, NULL, 0, mdctx, 1);
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1);
client_setup_transport(&cs, transport, mdctx);
GPR_ASSERT(f->client);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
}
static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
@ -123,9 +123,9 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
f->server = grpc_server_create_from_filters(NULL, 0, server_args);
grpc_server_register_completion_queue(f->server, f->cq);
grpc_server_start(f->server);
transport =
grpc_create_chttp2_transport(server_args, sfd->server, NULL, 0, mdctx, 0);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0);
server_setup_transport(f, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
}
static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) {

@ -108,10 +108,10 @@ static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f,
sp_client_setup cs;
cs.client_args = client_args;
cs.f = f;
transport =
grpc_create_chttp2_transport(client_args, sfd->client, NULL, 0, mdctx, 1);
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1);
client_setup_transport(&cs, transport, mdctx);
GPR_ASSERT(f->client);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
}
static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
@ -123,9 +123,9 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
f->server = grpc_server_create_from_filters(NULL, 0, server_args);
grpc_server_register_completion_queue(f->server, f->cq);
grpc_server_start(f->server);
transport =
grpc_create_chttp2_transport(server_args, sfd->server, NULL, 0, mdctx, 0);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0);
server_setup_transport(f, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
}
static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) {

@ -109,10 +109,10 @@ static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f,
sp_client_setup cs;
cs.client_args = client_args;
cs.f = f;
transport =
grpc_create_chttp2_transport(client_args, sfd->client, NULL, 0, mdctx, 1);
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1);
client_setup_transport(&cs, transport, mdctx);
GPR_ASSERT(f->client);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
}
static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
@ -124,9 +124,9 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
f->server = grpc_server_create_from_filters(NULL, 0, server_args);
grpc_server_register_completion_queue(f->server, f->cq);
grpc_server_start(f->server);
transport =
grpc_create_chttp2_transport(server_args, sfd->server, NULL, 0, mdctx, 0);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0);
server_setup_transport(f, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
}
static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) {

@ -160,6 +160,30 @@ static void test_read_deflate_compressed_slice(void) {
read_compressed_slice(GRPC_COMPRESS_DEFLATE, INPUT_SIZE);
}
static void test_byte_buffer_from_reader(void) {
gpr_slice slice;
grpc_byte_buffer *buffer, *buffer_from_reader;
grpc_byte_buffer_reader reader;
LOG_TEST("test_byte_buffer_from_reader");
slice = gpr_slice_malloc(4);
memcpy(GPR_SLICE_START_PTR(slice), "test", 4);
buffer = grpc_raw_byte_buffer_create(&slice, 1);
gpr_slice_unref(slice);
grpc_byte_buffer_reader_init(&reader, buffer);
buffer_from_reader = grpc_raw_byte_buffer_from_reader(&reader);
GPR_ASSERT(buffer->type == buffer_from_reader->type);
GPR_ASSERT(buffer_from_reader->data.raw.compression == GRPC_COMPRESS_NONE);
GPR_ASSERT(buffer_from_reader->data.raw.slice_buffer.count == 1);
GPR_ASSERT(memcmp(GPR_SLICE_START_PTR(
buffer_from_reader->data.raw.slice_buffer.slices[0]),
"test", 4) == 0);
grpc_byte_buffer_destroy(buffer);
grpc_byte_buffer_destroy(buffer_from_reader);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_read_one_slice();
@ -167,6 +191,7 @@ int main(int argc, char **argv) {
test_read_none_compressed_slice();
test_read_gzip_compressed_slice();
test_read_deflate_compressed_slice();
test_byte_buffer_from_reader();
return 0;
}

@ -0,0 +1,71 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
import "test/cpp/qps/qpstest.proto";
package grpc.testing;
service PerfDbTransfer {
// Sends client info
rpc RecordSingleClientData(SingleUserRecordRequest)
returns (SingleUserRecordReply) {
}
}
// Metrics to be stored
message Metrics {
double qps = 1;
double qps_per_core = 2;
double perc_lat_50 = 3;
double perc_lat_90 = 4;
double perc_lat_95 = 5;
double perc_lat_99 = 6;
double perc_lat_99_point_9 = 7;
double server_system_time = 8;
double server_user_time = 9;
double client_system_time = 10;
double client_user_time = 11;
}
// Request for storing a single user's data
message SingleUserRecordRequest {
string hashed_id = 1;
string test_name = 2;
string sys_info = 3;
string tag = 4;
Metrics metrics = 5;
ClientConfig client_config = 6;
ServerConfig server_config = 7;
}
// Reply to request for storing single user's data
message SingleUserRecordReply {
}

@ -0,0 +1,143 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/cpp/qps/perf_db_client.h"
namespace grpc {
namespace testing {
// sets the client and server config information
void PerfDbClient::setConfigs(const ClientConfig& client_config,
const ServerConfig& server_config) {
client_config_ = client_config;
server_config_ = server_config;
}
// sets the QPS
void PerfDbClient::setQps(double qps) {
qps_ = qps;
}
// sets the QPS per core
void PerfDbClient::setQpsPerCore(double qps_per_core) {
qps_per_core_ = qps_per_core;
}
// sets the 50th, 90th, 95th, 99th and 99.9th percentile latency
void PerfDbClient::setLatencies(double perc_lat_50,
double perc_lat_90,
double perc_lat_95,
double perc_lat_99,
double perc_lat_99_point_9) {
perc_lat_50_ = perc_lat_50;
perc_lat_90_ = perc_lat_90;
perc_lat_95_ = perc_lat_95;
perc_lat_99_ = perc_lat_99;
perc_lat_99_point_9_ = perc_lat_99_point_9;
}
// sets the server and client, user and system times
void PerfDbClient::setTimes(double server_system_time, double server_user_time,
double client_system_time, double client_user_time) {
server_system_time_ = server_system_time;
server_user_time_ = server_user_time;
client_system_time_ = client_system_time;
client_user_time_ = client_user_time;
}
// sends the data to the performance database server
bool PerfDbClient::sendData(std::string hashed_id, std::string test_name,
std::string sys_info, std::string tag) {
// Data record request object
SingleUserRecordRequest single_user_record_request;
// setting access token, name of the test and the system information
single_user_record_request.set_hashed_id(hashed_id);
single_user_record_request.set_test_name(test_name);
single_user_record_request.set_sys_info(sys_info);
single_user_record_request.set_tag(tag);
// setting configs
*(single_user_record_request.mutable_client_config()) = client_config_;
*(single_user_record_request.mutable_server_config()) = server_config_;
Metrics* metrics = single_user_record_request.mutable_metrics();
// setting metrcs in data record request
if (qps_ != DBL_MIN) {
metrics->set_qps(qps_);
}
if (qps_per_core_ != DBL_MIN) {
metrics->set_qps_per_core(qps_per_core_);
}
if (perc_lat_50_ != DBL_MIN) {
metrics->set_perc_lat_50(perc_lat_50_);
}
if (perc_lat_90_ != DBL_MIN) {
metrics->set_perc_lat_90(perc_lat_90_);
}
if (perc_lat_95_ != DBL_MIN) {
metrics->set_perc_lat_95(perc_lat_95_);
}
if (perc_lat_99_ != DBL_MIN) {
metrics->set_perc_lat_99(perc_lat_99_);
}
if (perc_lat_99_point_9_ != DBL_MIN) {
metrics->set_perc_lat_99_point_9(perc_lat_99_point_9_);
}
if (server_system_time_ != DBL_MIN) {
metrics->set_server_system_time(server_system_time_);
}
if (server_user_time_ != DBL_MIN) {
metrics->set_server_user_time(server_user_time_);
}
if (client_system_time_ != DBL_MIN) {
metrics->set_client_system_time(client_system_time_);
}
if (client_user_time_ != DBL_MIN) {
metrics->set_client_user_time(client_user_time_);
}
SingleUserRecordReply single_user_record_reply;
ClientContext context;
Status status = stub_->RecordSingleClientData(
&context, single_user_record_request, &single_user_record_reply);
if (status.ok()) {
return true; // data sent to database successfully
} else {
return false; // error in data sending
}
}
} // testing
} // grpc

@ -0,0 +1,115 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <memory>
#include <string>
#include <cfloat>
#include <grpc/grpc.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/status.h>
#include "test/cpp/qps/perf_db.grpc.pb.h"
namespace grpc {
namespace testing {
// Manages data sending to performance database server
class PerfDbClient {
public:
PerfDbClient() {
qps_ = DBL_MIN;
qps_per_core_ = DBL_MIN;
perc_lat_50_ = DBL_MIN;
perc_lat_90_ = DBL_MIN;
perc_lat_95_ = DBL_MIN;
perc_lat_99_ = DBL_MIN;
perc_lat_99_point_9_ = DBL_MIN;
server_system_time_ = DBL_MIN;
server_user_time_ = DBL_MIN;
client_system_time_ = DBL_MIN;
client_user_time_ = DBL_MIN;
}
void init(std::shared_ptr<ChannelInterface> channel) {
stub_ = PerfDbTransfer::NewStub(channel);
}
~PerfDbClient() {}
// sets the client and server config information
void setConfigs(const ClientConfig& client_config,
const ServerConfig& server_config);
// sets the qps
void setQps(double qps);
// sets the qps per core
void setQpsPerCore(double qps_per_core);
// sets the 50th, 90th, 95th, 99th and 99.9th percentile latency
void setLatencies(double perc_lat_50, double perc_lat_90,
double perc_lat_95, double perc_lat_99,
double perc_lat_99_point_9);
// sets the server and client, user and system times
void setTimes(double server_system_time, double server_user_time,
double client_system_time, double client_user_time);
// sends the data to the performance database server
bool sendData(std::string hashed_id, std::string test_name,
std::string sys_info, std::string tag);
private:
std::unique_ptr<PerfDbTransfer::Stub> stub_;
ClientConfig client_config_;
ServerConfig server_config_;
double qps_;
double qps_per_core_;
double perc_lat_50_;
double perc_lat_90_;
double perc_lat_95_;
double perc_lat_99_;
double perc_lat_99_point_9_;
double server_system_time_;
double server_user_time_;
double client_system_time_;
double client_user_time_;
};
} // namespace testing
} // namespace grpc

@ -67,7 +67,6 @@ void CompositeReporter::ReportTimes(const ScenarioResult& result) {
}
}
void GprLogReporter::ReportQPS(const ScenarioResult& result) {
gpr_log(GPR_INFO, "QPS: %.1f",
result.latencies.Count() /
@ -76,8 +75,7 @@ void GprLogReporter::ReportQPS(const ScenarioResult& result) {
}
void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result) {
auto qps =
result.latencies.Count() /
auto qps = result.latencies.Count() /
average(result.client_resources,
[](ResourceUsage u) { return u.wall_time; });
@ -118,5 +116,71 @@ void GprLogReporter::ReportTimes(const ScenarioResult& result) {
[](ResourceUsage u) { return u.wall_time; }));
}
void PerfDbReporter::ReportQPS(const ScenarioResult& result) {
auto qps = result.latencies.Count() /
average(result.client_resources,
[](ResourceUsage u) { return u.wall_time; });
perf_db_client_.setQps(qps);
perf_db_client_.setConfigs(result.client_config, result.server_config);
}
void PerfDbReporter::ReportQPSPerCore(const ScenarioResult& result) {
auto qps = result.latencies.Count() /
average(result.client_resources,
[](ResourceUsage u) { return u.wall_time; });
auto qpsPerCore = qps / result.server_config.threads();
perf_db_client_.setQps(qps);
perf_db_client_.setQpsPerCore(qpsPerCore);
perf_db_client_.setConfigs(result.client_config, result.server_config);
}
void PerfDbReporter::ReportLatency(const ScenarioResult& result) {
perf_db_client_.setLatencies(result.latencies.Percentile(50) / 1000,
result.latencies.Percentile(90) / 1000,
result.latencies.Percentile(95) / 1000,
result.latencies.Percentile(99) / 1000,
result.latencies.Percentile(99.9) / 1000);
perf_db_client_.setConfigs(result.client_config, result.server_config);
}
void PerfDbReporter::ReportTimes(const ScenarioResult& result) {
double server_system_time =
100.0 * sum(result.server_resources,
[](ResourceUsage u) { return u.system_time; }) /
sum(result.server_resources, [](ResourceUsage u) { return u.wall_time; });
double server_user_time =
100.0 * sum(result.server_resources,
[](ResourceUsage u) { return u.user_time; }) /
sum(result.server_resources, [](ResourceUsage u) { return u.wall_time; });
double client_system_time =
100.0 * sum(result.client_resources,
[](ResourceUsage u) { return u.system_time; }) /
sum(result.client_resources, [](ResourceUsage u) { return u.wall_time; });
double client_user_time =
100.0 * sum(result.client_resources,
[](ResourceUsage u) { return u.user_time; }) /
sum(result.client_resources, [](ResourceUsage u) { return u.wall_time; });
perf_db_client_.setTimes(server_system_time, server_user_time, client_system_time,
client_user_time);
perf_db_client_.setConfigs(result.client_config, result.server_config);
}
void PerfDbReporter::SendData() {
// send data to performance database
bool data_state =
perf_db_client_.sendData(hashed_id_, test_name_, sys_info_, tag_);
// check state of data sending
if (data_state) {
gpr_log(GPR_INFO, "Data sent to performance database successfully");
} else {
gpr_log(GPR_INFO, "Data could not be sent to performance database");
}
}
} // namespace testing
} // namespace grpc

@ -41,6 +41,7 @@
#include "test/cpp/qps/driver.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/perf_db_client.h"
namespace grpc {
namespace testing {
@ -103,6 +104,35 @@ class GprLogReporter : public Reporter {
void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
};
/** Reporter for performance database tool */
class PerfDbReporter : public Reporter {
public:
PerfDbReporter(const string& name, const string& hashed_id,
const string& test_name, const string& sys_info,
const string& server_address, const string& tag)
: Reporter(name),
hashed_id_(hashed_id),
test_name_(test_name),
sys_info_(sys_info),
tag_(tag) {
perf_db_client_.init(grpc::CreateChannel(
server_address, grpc::InsecureCredentials(), ChannelArguments()));
}
~PerfDbReporter() GRPC_OVERRIDE { SendData(); };
private:
PerfDbClient perf_db_client_;
std::string hashed_id_;
std::string test_name_;
std::string sys_info_;
std::string tag_;
void ReportQPS(const ScenarioResult& result) GRPC_OVERRIDE;
void ReportQPSPerCore(const ScenarioResult& result) GRPC_OVERRIDE;
void ReportLatency(const ScenarioResult& result) GRPC_OVERRIDE;
void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
void SendData();
};
} // namespace testing
} // namespace grpc

@ -64,7 +64,7 @@ namespace testing {
class AsyncQpsServerTest : public Server {
public:
AsyncQpsServerTest(const ServerConfig &config, int port) : shutdown_(false) {
AsyncQpsServerTest(const ServerConfig &config, int port) {
char *server_address = NULL;
gpr_join_host_port(&server_address, "::", port);
@ -96,6 +96,9 @@ class AsyncQpsServerTest : public Server {
request_streaming, ProcessRPC));
}
}
for (int i = 0; i < config.threads(); i++) {
shutdown_state_.emplace_back(new PerThreadShutdownState());
}
for (int i = 0; i < config.threads(); i++) {
threads_.push_back(std::thread([=]() {
// Wait until work is available or we are shutting down
@ -105,11 +108,9 @@ class AsyncQpsServerTest : public Server {
ServerRpcContext *ctx = detag(got_tag);
// The tag is a pointer to an RPC context to invoke
bool still_going = ctx->RunNextState(ok);
std::unique_lock<std::mutex> g(shutdown_mutex_);
if (!shutdown_) {
if (!shutdown_state_[i]->shutdown()) {
// this RPC context is done, so refresh it
if (!still_going) {
g.unlock();
ctx->Reset();
}
} else {
@ -122,9 +123,8 @@ class AsyncQpsServerTest : public Server {
}
~AsyncQpsServerTest() {
server_->Shutdown();
{
std::lock_guard<std::mutex> g(shutdown_mutex_);
shutdown_ = true;
for (auto ss = shutdown_state_.begin(); ss != shutdown_state_.end(); ++ss) {
(*ss)->set_shutdown();
}
for (auto thr = threads_.begin(); thr != threads_.end(); thr++) {
thr->join();
@ -316,8 +316,25 @@ class AsyncQpsServerTest : public Server {
TestService::AsyncService async_service_;
std::forward_list<ServerRpcContext *> contexts_;
std::mutex shutdown_mutex_;
class PerThreadShutdownState {
public:
PerThreadShutdownState() : shutdown_(false) {}
bool shutdown() const {
std::lock_guard<std::mutex> lock(mutex_);
return shutdown_;
}
void set_shutdown() {
std::lock_guard<std::mutex> lock(mutex_);
shutdown_ = true;
}
private:
mutable std::mutex mutex_;
bool shutdown_;
};
std::vector<std::unique_ptr<PerThreadShutdownState>> shutdown_state_;
};
std::unique_ptr<Server> CreateAsyncServer(const ServerConfig &config,

@ -37,6 +37,18 @@
DEFINE_bool(enable_log_reporter, true,
"Enable reporting of benchmark results through GprLog");
DEFINE_bool(report_metrics_db, false, "True if metrics to be reported to performance database");
DEFINE_string(hashed_id, "", "Hash of the user id");
DEFINE_string(test_name, "", "Name of the test being executed");
DEFINE_string(sys_info, "", "System information");
DEFINE_string(server_address, "localhost:50052", "Address of the performance database server");
DEFINE_string(tag, "", "Optional tag for the test");
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
@ -57,6 +69,12 @@ static std::shared_ptr<Reporter> InitBenchmarkReporters() {
composite_reporter->add(
std::unique_ptr<Reporter>(new GprLogReporter("LogReporter")));
}
if(FLAGS_report_metrics_db) {
composite_reporter->add(
std::unique_ptr<Reporter>(new PerfDbReporter("PerfDbReporter", FLAGS_hashed_id, FLAGS_test_name,
FLAGS_sys_info, FLAGS_server_address, FLAGS_tag)));
}
return std::shared_ptr<Reporter>(composite_reporter);
}

@ -9881,6 +9881,9 @@
"test/cpp/qps/driver.h",
"test/cpp/qps/histogram.h",
"test/cpp/qps/interarrival.h",
"test/cpp/qps/perf_db.grpc.pb.h",
"test/cpp/qps/perf_db.pb.h",
"test/cpp/qps/perf_db_client.h",
"test/cpp/qps/qps_worker.h",
"test/cpp/qps/qpstest.grpc.pb.h",
"test/cpp/qps/qpstest.pb.h",
@ -9900,6 +9903,8 @@
"test/cpp/qps/driver.h",
"test/cpp/qps/histogram.h",
"test/cpp/qps/interarrival.h",
"test/cpp/qps/perf_db_client.cc",
"test/cpp/qps/perf_db_client.h",
"test/cpp/qps/qps_worker.cc",
"test/cpp/qps/qps_worker.h",
"test/cpp/qps/report.cc",

Loading…
Cancel
Save