Merge branch 'we-dont-need-no-backup' of github.com:ctiller/grpc into we-dont-need-no-backup

pull/1888/head
Craig Tiller 10 years ago
commit dfbb26aa95
  1. 8
      Makefile
  2. 25
      gRPC.podspec
  3. 4
      include/grpc++/server_context.h
  4. 86
      src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
  5. 4
      src/ruby/bin/interop/interop_client.rb
  6. 11
      src/ruby/lib/grpc/generic/active_call.rb
  7. 64
      src/ruby/lib/grpc/generic/bidi_call.rb
  8. 4
      templates/Makefile.template
  9. 33
      test/cpp/qps/server_async.cc

@ -262,6 +262,8 @@ LDFLAGS += -fPIC
endif
INCLUDES = . include $(GENDIR)
LDFLAGS += -Llibs/$(CONFIG)
ifeq ($(SYSTEM),Darwin)
ifneq ($(wildcard /usr/local/ssl/include),)
INCLUDES += /usr/local/ssl/include
@ -3075,15 +3077,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc-imp.a -o $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr-imp
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc-imp.a -o $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) -lgpr-imp
else
$(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin)
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name libgrpc.$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name libgrpc.$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) -lgpr
else
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) -lgpr
$(Q) ln -sf libgrpc.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.so.0
$(Q) ln -sf libgrpc.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.so
endif

@ -1,13 +1,13 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
s.version = '0.0.1'
s.summary = 'Generic gRPC client library for iOS/OSX'
s.homepage = 'https://www.grpc.io'
s.version = '0.5.1'
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'
s.license = 'New BSD'
s.authors = { 'Jorge Canizales' => 'jcanizales@google.com',
'Michael Lumish' => 'mlumish@google.com' }
s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' }
# s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => 'release-0_5_0' }
# s.source = { :git => 'https://github.com/grpc/grpc.git',
# :tag => 'release-0_9_1-objectivec-0.5.1' }
s.ios.deployment_target = '6.0'
s.osx.deployment_target = '10.8'
@ -15,7 +15,6 @@ Pod::Spec.new do |s|
s.subspec 'RxLibrary' do |rs|
rs.summary = 'Reactive Extensions library for iOS.'
rs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}',
'src/objective-c/RxLibrary/transformations/*.{h,m}',
@ -25,16 +24,13 @@ Pod::Spec.new do |s|
s.subspec 'C-Core' do |cs|
cs.summary = 'Core cross-platform gRPC library, written in C.'
cs.authors = { 'Craig Tiller' => 'ctiller@google.com',
'David Klempner' => 'klempner@google.com',
'Nicolas Noble' => 'nnoble@google.com',
'Vijay Pai' => 'vpai@google.com',
'Yang Gao' => 'yangg@google.com' }
cs.source_files = 'src/core/**/*.{h,c}', 'include/grpc/*.h', 'include/grpc/**/*.h'
cs.private_header_files = 'src/core/**/*.h'
cs.header_mappings_dir = '.'
cs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Build/gRPC" "$(PODS_ROOT)/Headers/Build/gRPC/include"' }
cs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Build/gRPC" '
'"$(PODS_ROOT)/Headers/Build/gRPC/include"' }
cs.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
cs.requires_arc = false
cs.libraries = 'z'
@ -67,8 +63,6 @@ Pod::Spec.new do |s|
s.subspec 'GRPCClient' do |gs|
gs.summary = 'Objective-C wrapper around the core gRPC library.'
gs.authors = { 'Jorge Canizales' => 'jcanizales@google.com',
'Michael Lumish' => 'mlumish@google.com' }
gs.source_files = 'src/objective-c/GRPCClient/*.{h,m}',
'src/objective-c/GRPCClient/private/*.{h,m}'
@ -85,7 +79,6 @@ Pod::Spec.new do |s|
s.subspec 'ProtoRPC' do |ps|
ps.summary = 'RPC library for ProtocolBuffers, based on gRPC'
ps.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
ps.source_files = 'src/objective-c/ProtoRPC/*.{h,m}'

@ -106,6 +106,10 @@ class ServerContext {
template <class R, class W>
friend class ::grpc::ServerReaderWriter;
// Prevent copying.
ServerContext(const ServerContext&);
ServerContext& operator=(const ServerContext&);
class CompletionOp;
void BeginCompletionOp(Call* call);

@ -35,21 +35,90 @@
#include <grpc/support/alloc.h>
#pragma mark Category for binary metadata elements
@interface NSData (GRPCMetadata)
+ (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata;
// Fill a metadata object with the binary value in this NSData and the given key.
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key;
@end
@implementation NSData (GRPCMetadata)
+ (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata {
// TODO(jcanizales): Should we use a non-copy constructor?
return [self dataWithBytes:metadata->value length:metadata->value_length];
}
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key {
// TODO(jcanizales): Encode Unicode chars as ASCII.
metadata->key = [key stringByAppendingString:@"-bin"].UTF8String;
metadata->value = self.bytes;
metadata->value_length = self.length;
}
@end
#pragma mark Category for textual metadata elements
@interface NSString (GRPCMetadata)
+ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata;
// Fill a metadata object with the textual value in this NSString and the given key.
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key;
@end
@implementation NSString (GRPCMetadata)
+ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata {
return [[self alloc] initWithBytes:metadata->value
length:metadata->value_length
encoding:NSASCIIStringEncoding];
}
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key {
if ([key hasSuffix:@"-bin"]) {
// Disallow this, as at best it will confuse the server. If the app really needs to send a
// textual header with a name ending in "-bin", it can be done by removing the suffix and
// encoding the NSString as a NSData object.
//
// Why raise an exception: In the most common case, the developer knows this won't happen in
// their code, so the exception isn't triggered. In the rare cases when the developer can't
// tell, it's easy enough to add a sanitizing filter before the header is set. There, the
// developer can choose whether to drop such a header, or trim its name. Doing either ourselves,
// silently, would be very unintuitive for the user.
[NSException raise:NSInvalidArgumentException
format:@"Metadata keys ending in '-bin' are reserved for NSData values."];
}
// TODO(jcanizales): Encode Unicode chars as ASCII.
metadata->key = key.UTF8String;
metadata->value = self.UTF8String;
metadata->value_length = self.length;
}
@end
#pragma mark Category for metadata arrays
@implementation NSDictionary (GRPC)
+ (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count {
NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count];
for (grpc_metadata *entry = entries; entry < entries + count; entry++) {
// TODO(jcanizales): Verify in a C library test that it's converting header names to lower case automatically.
NSString *name = [NSString stringWithUTF8String:entry->key];
// TODO(jcanizales): Verify in a C library test that it's converting header names to lower case
// automatically.
NSString *name = [NSString stringWithCString:entry->key encoding:NSASCIIStringEncoding];
if (!name) {
// log?
continue;
}
id value;
if ([name hasSuffix:@"-bin"]) {
name = [name substringToIndex:name.length - 4];
value = [NSData grpc_dataFromMetadataValue:entry];
} else {
value = [NSString grpc_stringFromMetadataValue:entry];
}
if (!metadata[name]) {
metadata[name] = [NSMutableArray array];
}
// TODO(jcanizales): Should we use a non-copy constructor?
[metadata[name] addObject:[NSData dataWithBytes:entry->value
length:entry->value_length]];
[metadata[name] addObject:value];
}
return metadata;
}
@ -60,11 +129,8 @@
for (id key in self) {
id value = self[key];
grpc_metadata *current = &metadata[i];
current->key = [key UTF8String];
if ([value isKindOfClass:[NSData class]]) {
current->value = [value bytes];
} else if ([value isKindOfClass:[NSString class]]) {
current->value = [value UTF8String];
if ([value respondsToSelector:@selector(grpc_initMetadata:withKey:)]) {
[value grpc_initMetadata:current withKey:key];
} else {
[NSException raise:NSInvalidArgumentException
format:@"Metadata values must be NSString or NSData."];

@ -274,6 +274,7 @@ class NamedTests
op = @stub.streaming_input_call(reqs, return_op: true)
op.cancel
assert_raises(GRPC::Cancelled) { op.execute }
assert(op.cancelled, 'call operation should be CANCELLED')
p 'OK: cancel_after_begin'
end
@ -282,7 +283,8 @@ class NamedTests
ppp = PingPongPlayer.new(msg_sizes)
op = @stub.full_duplex_call(ppp.each_item, return_op: true)
ppp.canceller_op = op # causes ppp to cancel after the 1st message
assert_raises(GRPC::Cancelled) { op.execute.each { |r| ppp.queue.push(r) } }
op.execute.each { |r| ppp.queue.push(r) }
assert(op.cancelled, 'call operation should be CANCELLED')
p 'OK: cancel_after_first_response'
end

@ -55,7 +55,6 @@ module GRPC
# The ActiveCall class provides simple methods for sending marshallable
# data to a call
class ActiveCall
include Core::StatusCodes
include Core::TimeConsts
include Core::CallOps
extend Forwardable
@ -129,6 +128,11 @@ module GRPC
@output_metadata ||= {}
end
# cancelled indicates if the call was cancelled
def cancelled
!@call.status.nil? && @call.status.code == Core::StatusCodes::CANCELLED
end
# multi_req_view provides a restricted view of this ActiveCall for use
# in a server client-streaming handler.
def multi_req_view
@ -162,6 +166,7 @@ module GRPC
ops[RECV_STATUS_ON_CLIENT] = nil if assert_finished
batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE, ops)
return unless assert_finished
@call.status = batch_result.status
batch_result.check_status
end
@ -178,6 +183,7 @@ module GRPC
@call.metadata.merge!(batch_result.status.metadata)
end
end
@call.status = batch_result.status
batch_result.check_status
end
@ -410,9 +416,6 @@ module GRPC
start_call(**kw) unless @started
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal, @deadline)
bd.run_on_client(requests, &blk)
rescue GRPC::Core::CallError => e
finished # checks for Cancelled
raise e
end
# run_server_bidi orchestrates a BiDi stream processing on a server.

@ -78,11 +78,9 @@ module GRPC
# @param requests the Enumerable of requests to send
# @return an Enumerator of requests to yield
def run_on_client(requests, &blk)
@enq_th = start_write_loop(requests)
@enq_th = Thread.new { write_loop(requests) }
@loop_th = start_read_loop
replies = each_queued_msg
return replies if blk.nil?
replies.each { |r| blk.call(r) }
each_queued_msg(&blk)
end
# Begins orchestration of the Bidi stream for a server generating replies.
@ -98,9 +96,8 @@ module GRPC
# @param gen_each_reply [Proc] generates the BiDi stream replies.
def run_on_server(gen_each_reply)
replys = gen_each_reply.call(each_queued_msg)
@enq_th = start_write_loop(replys, is_client: false)
@loop_th = start_read_loop
@enq_th.join if @enq_th.alive?
write_loop(replys, is_client: false)
end
private
@ -126,37 +123,32 @@ module GRPC
end
end
# during bidi-streaming, read the requests to send from a separate thread
# read so that read_loop does not block waiting for requests to read.
def start_write_loop(requests, is_client: true)
Thread.new do # TODO: run on a thread pool
GRPC.logger.debug('bidi-write-loop: starting')
begin
write_tag = Object.new
count = 0
requests.each do |req|
GRPC.logger.debug("bidi-write-loop: #{count}")
count += 1
payload = @marshal.call(req)
@call.run_batch(@cq, write_tag, INFINITE_FUTURE,
SEND_MESSAGE => payload)
end
GRPC.logger.debug("bidi-write-loop: #{count} writes done")
if is_client
GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting")
@call.run_batch(@cq, write_tag, INFINITE_FUTURE,
SEND_CLOSE_FROM_CLIENT => nil)
batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE,
RECV_STATUS_ON_CLIENT => nil)
batch_result.check_status
end
rescue StandardError => e
GRPC.logger.warn('bidi-write-loop: failed')
GRPC.logger.warn(e)
raise e
end
GRPC.logger.debug('bidi-write-loop: finished')
def write_loop(requests, is_client: true)
GRPC.logger.debug('bidi-write-loop: starting')
write_tag = Object.new
count = 0
requests.each do |req|
GRPC.logger.debug("bidi-write-loop: #{count}")
count += 1
payload = @marshal.call(req)
@call.run_batch(@cq, write_tag, INFINITE_FUTURE,
SEND_MESSAGE => payload)
end
GRPC.logger.debug("bidi-write-loop: #{count} writes done")
if is_client
GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting")
batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE,
SEND_CLOSE_FROM_CLIENT => nil,
RECV_STATUS_ON_CLIENT => nil)
@call.status = batch_result.status
batch_result.check_status
GRPC.logger.debug("bidi-write-loop: done status #{@call.status}")
end
GRPC.logger.debug('bidi-write-loop: finished')
rescue StandardError => e
GRPC.logger.warn('bidi-write-loop: failed')
GRPC.logger.warn(e)
raise e
end
# starts the read loop

@ -276,6 +276,8 @@ LDFLAGS += -fPIC
endif
INCLUDES = . include $(GENDIR)
LDFLAGS += -Llibs/$(CONFIG)
ifeq ($(SYSTEM),Darwin)
ifneq ($(wildcard /usr/local/ssl/include),)
INCLUDES += /usr/local/ssl/include
@ -1220,7 +1222,7 @@ endif
mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '.$(SHARED_EXT)'
if lib.get('secure', 'check') == 'yes':
common = common + ' $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS)'
common = common + ' $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE)'
for src in lib.src:
sources_that_need_openssl.add(src)
else:

@ -33,6 +33,7 @@
#include <forward_list>
#include <functional>
#include <memory>
#include <mutex>
#include <sys/time.h>
#include <sys/resource.h>
@ -158,11 +159,12 @@ class AsyncQpsServerTest : public Server {
void *)> request_method,
std::function<grpc::Status(const RequestType *, ResponseType *)>
invoke_method)
: next_state_(&ServerRpcContextUnaryImpl::invoker),
: srv_ctx_(new ServerContext),
next_state_(&ServerRpcContextUnaryImpl::invoker),
request_method_(request_method),
invoke_method_(invoke_method),
response_writer_(&srv_ctx_) {
request_method_(&srv_ctx_, &req_, &response_writer_,
response_writer_(srv_ctx_.get()) {
request_method_(srv_ctx_.get(), &req_, &response_writer_,
AsyncQpsServerTest::tag(this));
}
~ServerRpcContextUnaryImpl() GRPC_OVERRIDE {}
@ -170,14 +172,14 @@ class AsyncQpsServerTest : public Server {
return (this->*next_state_)(ok);
}
void Reset() GRPC_OVERRIDE {
srv_ctx_ = ServerContext();
srv_ctx_.reset(new ServerContext);
req_ = RequestType();
response_writer_ =
grpc::ServerAsyncResponseWriter<ResponseType>(&srv_ctx_);
grpc::ServerAsyncResponseWriter<ResponseType>(srv_ctx_.get());
// Then request the method
next_state_ = &ServerRpcContextUnaryImpl::invoker;
request_method_(&srv_ctx_, &req_, &response_writer_,
request_method_(srv_ctx_.get(), &req_, &response_writer_,
AsyncQpsServerTest::tag(this));
}
@ -198,7 +200,7 @@ class AsyncQpsServerTest : public Server {
response_writer_.Finish(response, status, AsyncQpsServerTest::tag(this));
return true;
}
ServerContext srv_ctx_;
std::unique_ptr<ServerContext> srv_ctx_;
RequestType req_;
bool (ServerRpcContextUnaryImpl::*next_state_)(bool);
std::function<void(ServerContext *, RequestType *,
@ -218,25 +220,26 @@ class AsyncQpsServerTest : public Server {
void *)> request_method,
std::function<grpc::Status(const RequestType *, ResponseType *)>
invoke_method)
: next_state_(&ServerRpcContextStreamingImpl::request_done),
: srv_ctx_(new ServerContext),
next_state_(&ServerRpcContextStreamingImpl::request_done),
request_method_(request_method),
invoke_method_(invoke_method),
stream_(&srv_ctx_) {
request_method_(&srv_ctx_, &stream_, AsyncQpsServerTest::tag(this));
stream_(srv_ctx_.get()) {
request_method_(srv_ctx_.get(), &stream_, AsyncQpsServerTest::tag(this));
}
~ServerRpcContextStreamingImpl() GRPC_OVERRIDE {}
bool RunNextState(bool ok) GRPC_OVERRIDE {
return (this->*next_state_)(ok);
}
void Reset() GRPC_OVERRIDE {
srv_ctx_ = ServerContext();
srv_ctx_.reset(new ServerContext);
req_ = RequestType();
stream_ =
grpc::ServerAsyncReaderWriter<ResponseType, RequestType>(&srv_ctx_);
stream_ = grpc::ServerAsyncReaderWriter<ResponseType, RequestType>(
srv_ctx_.get());
// Then request the method
next_state_ = &ServerRpcContextStreamingImpl::request_done;
request_method_(&srv_ctx_, &stream_, AsyncQpsServerTest::tag(this));
request_method_(srv_ctx_.get(), &stream_, AsyncQpsServerTest::tag(this));
}
private:
@ -278,7 +281,7 @@ class AsyncQpsServerTest : public Server {
}
bool finish_done(bool ok) { return false; /* reset the context */ }
ServerContext srv_ctx_;
std::unique_ptr<ServerContext> srv_ctx_;
RequestType req_;
bool (ServerRpcContextStreamingImpl::*next_state_)(bool);
std::function<void(

Loading…
Cancel
Save