diff --git a/BUILD b/BUILD
index 33850871119..a6356006456 100644
--- a/BUILD
+++ b/BUILD
@@ -51,9 +51,9 @@ load(
# This should be updated along with build.yaml
g_stands_for = "gregarious"
-core_version = "3.0.0-dev"
+core_version = "4.0.0-dev"
-version = "1.4.0-dev"
+version = "1.5.0-dev"
grpc_cc_library(
name = "gpr",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1684f4cda60..99dd06c11c0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,7 +39,7 @@
cmake_minimum_required(VERSION 2.8)
set(PACKAGE_NAME "grpc")
-set(PACKAGE_VERSION "1.4.0-dev")
+set(PACKAGE_VERSION "1.5.0-dev")
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
@@ -482,6 +482,7 @@ add_dependencies(buildtests_c mlog_test)
add_dependencies(buildtests_c multiple_server_queues_test)
add_dependencies(buildtests_c murmur_hash_test)
add_dependencies(buildtests_c no_server_test)
+add_dependencies(buildtests_c num_external_connectivity_watchers_test)
add_dependencies(buildtests_c parse_address_test)
add_dependencies(buildtests_c percent_encoding_test)
if(_gRPC_PLATFORM_LINUX)
@@ -7513,6 +7514,37 @@ target_link_libraries(no_server_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
+add_executable(num_external_connectivity_watchers_test
+ test/core/surface/num_external_connectivity_watchers_test.c
+)
+
+
+target_include_directories(num_external_connectivity_watchers_test
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE ${BORINGSSL_ROOT_DIR}/include
+ PRIVATE ${PROTOBUF_ROOT_DIR}/src
+ PRIVATE ${BENCHMARK_ROOT_DIR}/include
+ PRIVATE ${ZLIB_ROOT_DIR}
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+ PRIVATE ${CARES_BUILD_INCLUDE_DIR}
+ PRIVATE ${CARES_INCLUDE_DIR}
+ PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(num_external_connectivity_watchers_test
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr_test_util
+ gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
add_executable(parse_address_test
test/core/client_channel/parse_address_test.c
)
diff --git a/Makefile b/Makefile
index 6699fbff5a9..718ddc573ba 100644
--- a/Makefile
+++ b/Makefile
@@ -423,8 +423,8 @@ Q = @
endif
CORE_VERSION = 4.0.0-dev
-CPP_VERSION = 1.4.0-dev
-CSHARP_VERSION = 1.4.0-dev
+CPP_VERSION = 1.5.0-dev
+CSHARP_VERSION = 1.5.0-dev
CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -1063,6 +1063,7 @@ murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test
nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test
nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test
no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
+num_external_connectivity_watchers_test: $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test
parse_address_test: $(BINDIR)/$(CONFIG)/parse_address_test
percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer
@@ -1442,6 +1443,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/multiple_server_queues_test \
$(BINDIR)/$(CONFIG)/murmur_hash_test \
$(BINDIR)/$(CONFIG)/no_server_test \
+ $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test \
$(BINDIR)/$(CONFIG)/parse_address_test \
$(BINDIR)/$(CONFIG)/percent_encoding_test \
$(BINDIR)/$(CONFIG)/pollset_set_test \
@@ -1911,6 +1913,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/murmur_hash_test || ( echo test murmur_hash_test failed ; exit 1 )
$(E) "[RUN] Testing no_server_test"
$(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 )
+ $(E) "[RUN] Testing num_external_connectivity_watchers_test"
+ $(Q) $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test || ( echo test num_external_connectivity_watchers_test failed ; exit 1 )
$(E) "[RUN] Testing parse_address_test"
$(Q) $(BINDIR)/$(CONFIG)/parse_address_test || ( echo test parse_address_test failed ; exit 1 )
$(E) "[RUN] Testing percent_encoding_test"
@@ -11756,6 +11760,38 @@ endif
endif
+NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC = \
+ test/core/surface/num_external_connectivity_watchers_test.c \
+
+NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/surface/num_external_connectivity_watchers_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
PARSE_ADDRESS_TEST_SRC = \
test/core/client_channel/parse_address_test.c \
diff --git a/build.yaml b/build.yaml
index 008933922b2..ab2195ebf64 100644
--- a/build.yaml
+++ b/build.yaml
@@ -14,7 +14,7 @@ settings:
'#10': See the expand_version.py for all the quirks here
core_version: 4.0.0-dev
g_stands_for: gregarious
- version: 1.4.0-dev
+ version: 1.5.0-dev
filegroups:
- name: census
public_headers:
@@ -2702,6 +2702,18 @@ targets:
- grpc
- gpr_test_util
- gpr
+- name: num_external_connectivity_watchers_test
+ build: test
+ language: c
+ src:
+ - test/core/surface/num_external_connectivity_watchers_test.c
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr_test_util
+ - gpr
+ exclude_iomgrs:
+ - uv
- name: parse_address_test
build: test
language: c
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 1053658ccec..3ebb5274afd 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -37,7 +37,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
- version = '1.4.0-dev'
+ version = '1.5.0-dev'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'http://www.grpc.io'
diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec
index 62cb0d11a1c..6baef288855 100644
--- a/gRPC-ProtoRPC.podspec
+++ b/gRPC-ProtoRPC.podspec
@@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
- version = '1.4.0-dev'
+ version = '1.5.0-dev'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'http://www.grpc.io'
diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec
index 77ceb22123c..dfccc5d16c4 100644
--- a/gRPC-RxLibrary.podspec
+++ b/gRPC-RxLibrary.podspec
@@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
- version = '1.4.0-dev'
+ version = '1.5.0-dev'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'http://www.grpc.io'
diff --git a/gRPC.podspec b/gRPC.podspec
index 10520bd3880..7f4886ab656 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -35,7 +35,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
- version = '1.4.0-dev'
+ version = '1.5.0-dev'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'
diff --git a/grpc.def b/grpc.def
index 55b27c2c245..af4bd1674f2 100644
--- a/grpc.def
+++ b/grpc.def
@@ -65,6 +65,7 @@ EXPORTS
grpc_alarm_cancel
grpc_alarm_destroy
grpc_channel_check_connectivity_state
+ grpc_channel_num_external_connectivity_watchers
grpc_channel_watch_connectivity_state
grpc_channel_create_call
grpc_channel_ping
diff --git a/include/grpc++/grpc++.h b/include/grpc++/grpc++.h
index d6c3e2e7683..a4f512dbee9 100644
--- a/include/grpc++/grpc++.h
+++ b/include/grpc++/grpc++.h
@@ -34,18 +34,18 @@
/// \mainpage gRPC C++ API
///
/// The gRPC C++ API mainly consists of the following classes:
-//
+///
/// - grpc::Channel, which represents the connection to an endpoint. See [the
/// gRPC Concepts page](http://www.grpc.io/docs/guides/concepts.html) for more
/// details. Channels are created by the factory function grpc::CreateChannel.
-//
+///
/// - grpc::CompletionQueue, the producer-consumer queue used for all
/// asynchronous communication with the gRPC runtime.
-//
+///
/// - grpc::ClientContext and grpc::ServerContext, where optional configuration
/// for an RPC can be set, such as setting custom metadata to be conveyed to the
/// peer, compression settings, authentication, etc.
-//
+///
/// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder.
///
/// Streaming calls are handled with the streaming classes in
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index f8b6d03e351..2843b518147 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -150,15 +150,16 @@ class ServerBuilder {
///
/// It can be invoked multiple times.
///
- /// \param addr The address to try to bind to the server (eg, localhost:1234,
- /// 192.168.1.1:31416, [::1]:27182, etc.).
+ /// \param addr_uri The address to try to bind to the server in URI form. If
+ /// the scheme name is omitted, "dns:///" is assumed. Valid values include
+ /// dns:///localhost:1234, / 192.168.1.1:31416, dns:///[::1]:27182, etc.).
/// \params creds The credentials associated with the server.
/// \param selected_port[out] If not `nullptr`, gets populated with the port
/// number bound to the \a grpc::Server for the corresponding endpoint after
/// it is successfully bound, 0 otherwise.
///
// TODO(dgq): the "port" part seems to be a misnomer.
- ServerBuilder& AddListeningPort(const grpc::string& addr,
+ ServerBuilder& AddListeningPort(const grpc::string& addr_uri,
std::shared_ptr creds,
int* selected_port = nullptr);
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index a36367fa8f9..47d1ea62380 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -178,6 +178,12 @@ GRPCAPI void grpc_alarm_destroy(grpc_alarm *alarm);
GRPCAPI grpc_connectivity_state grpc_channel_check_connectivity_state(
grpc_channel *channel, int try_to_connect);
+/** Number of active "external connectivity state watchers" attached to a
+ * channel.
+ * Useful for testing. **/
+GRPCAPI int grpc_channel_num_external_connectivity_watchers(
+ grpc_channel *channel);
+
/** Watch for a change in connectivity state.
Once the channel connectivity state is different from last_observed_state,
tag will be enqueued on cq with success=1.
diff --git a/package.json b/package.json
index 1ed182ced93..a0d76c435b6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "grpc",
- "version": "1.4.0-dev",
+ "version": "1.5.0-dev",
"author": "Google Inc.",
"description": "gRPC Library for Node",
"homepage": "http://www.grpc.io/",
diff --git a/package.xml b/package.xml
index 599442556f1..01641d7e0e1 100644
--- a/package.xml
+++ b/package.xml
@@ -13,8 +13,8 @@
2017-05-22
- 1.4.0dev
- 1.4.0dev
+ 1.5.0dev
+ 1.5.0dev
beta
diff --git a/src/core/ext/census/intrusive_hash_map.c b/src/core/ext/census/intrusive_hash_map.c
index 77512a3aac8..9f56b765e12 100644
--- a/src/core/ext/census/intrusive_hash_map.c
+++ b/src/core/ext/census/intrusive_hash_map.c
@@ -37,7 +37,7 @@
extern bool hm_index_compare(const hm_index *A, const hm_index *B);
/* Simple hashing function that takes lower 32 bits. */
-static inline uint32_t chunked_vector_hasher(uint64_t key) {
+static __inline uint32_t chunked_vector_hasher(uint64_t key) {
return (uint32_t)key;
}
@@ -45,8 +45,8 @@ static inline uint32_t chunked_vector_hasher(uint64_t key) {
static const size_t VECTOR_CHUNK_SIZE = (1 << 20) / sizeof(void *);
/* Helper functions which return buckets from the chunked vector. */
-static inline void **get_mutable_bucket(const chunked_vector *buckets,
- uint32_t index) {
+static __inline void **get_mutable_bucket(const chunked_vector *buckets,
+ uint32_t index) {
if (index < VECTOR_CHUNK_SIZE) {
return &buckets->first_[index];
}
@@ -54,7 +54,8 @@ static inline void **get_mutable_bucket(const chunked_vector *buckets,
return &buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE];
}
-static inline void *get_bucket(const chunked_vector *buckets, uint32_t index) {
+static __inline void *get_bucket(const chunked_vector *buckets,
+ uint32_t index) {
if (index < VECTOR_CHUNK_SIZE) {
return buckets->first_[index];
}
@@ -63,7 +64,7 @@ static inline void *get_bucket(const chunked_vector *buckets, uint32_t index) {
}
/* Helper function. */
-static inline size_t RestSize(const chunked_vector *vec) {
+static __inline size_t RestSize(const chunked_vector *vec) {
return (vec->size_ <= VECTOR_CHUNK_SIZE)
? 0
: (vec->size_ - VECTOR_CHUNK_SIZE - 1) / VECTOR_CHUNK_SIZE + 1;
@@ -222,9 +223,9 @@ hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key) {
* array_size-1. Returns true if it is a new hm_item and false if the hm_item
* already existed.
*/
-static inline bool intrusive_hash_map_internal_insert(chunked_vector *buckets,
- uint32_t hash_mask,
- hm_item *item) {
+static __inline bool intrusive_hash_map_internal_insert(chunked_vector *buckets,
+ uint32_t hash_mask,
+ hm_item *item) {
const uint64_t key = item->key;
uint32_t index = chunked_vector_hasher(key) & hash_mask;
hm_item **slot = (hm_item **)get_mutable_bucket(buckets, index);
diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h
index a8405517b89..e316bf4b161 100644
--- a/src/core/ext/census/intrusive_hash_map.h
+++ b/src/core/ext/census/intrusive_hash_map.h
@@ -101,7 +101,7 @@ typedef struct hm_index {
/* Returns true if two hm_indices point to the same object within the hash map
* and false otherwise. */
-inline bool hm_index_compare(const hm_index *A, const hm_index *B) {
+__inline bool hm_index_compare(const hm_index *A, const hm_index *B) {
return (A->item == B->item && A->bucket_index == B->bucket_index);
}
diff --git a/src/core/ext/filters/client_channel/channel_connectivity.c b/src/core/ext/filters/client_channel/channel_connectivity.c
index f83670db82e..04666edbec7 100644
--- a/src/core/ext/filters/client_channel/channel_connectivity.c
+++ b/src/core/ext/filters/client_channel/channel_connectivity.c
@@ -67,9 +67,8 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
typedef enum {
WAITING,
- CALLING_BACK,
+ READY_TO_CALL_BACK,
CALLING_BACK_AND_FINISHED,
- CALLED_BACK
} callback_phase;
typedef struct {
@@ -77,11 +76,13 @@ typedef struct {
callback_phase phase;
grpc_closure on_complete;
grpc_closure on_timeout;
+ grpc_closure watcher_timer_init;
grpc_timer alarm;
grpc_connectivity_state state;
grpc_completion_queue *cq;
grpc_cq_completion completion_storage;
grpc_channel *channel;
+ grpc_error *error;
void *tag;
} state_watcher;
@@ -105,11 +106,8 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
gpr_mu_lock(&w->mu);
switch (w->phase) {
case WAITING:
- case CALLED_BACK:
+ case READY_TO_CALL_BACK:
GPR_UNREACHABLE_CODE(return );
- case CALLING_BACK:
- w->phase = CALLED_BACK;
- break;
case CALLING_BACK_AND_FINISHED:
delete = 1;
break;
@@ -123,10 +121,14 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
bool due_to_completion, grpc_error *error) {
- int delete = 0;
-
if (due_to_completion) {
grpc_timer_cancel(exec_ctx, &w->alarm);
+ } else {
+ grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
+ grpc_channel_get_channel_stack(w->channel));
+ grpc_client_channel_watch_connectivity_state(exec_ctx, client_channel_elem,
+ grpc_cq_pollset(w->cq), NULL,
+ &w->on_complete, NULL);
}
gpr_mu_lock(&w->mu);
@@ -147,25 +149,27 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
}
switch (w->phase) {
case WAITING:
- w->phase = CALLING_BACK;
- grpc_cq_end_op(exec_ctx, w->cq, w->tag, GRPC_ERROR_REF(error),
- finished_completion, w, &w->completion_storage);
+ GRPC_ERROR_REF(error);
+ w->error = error;
+ w->phase = READY_TO_CALL_BACK;
break;
- case CALLING_BACK:
+ case READY_TO_CALL_BACK:
+ if (error != GRPC_ERROR_NONE) {
+ GPR_ASSERT(!due_to_completion);
+ GRPC_ERROR_UNREF(w->error);
+ GRPC_ERROR_REF(error);
+ w->error = error;
+ }
w->phase = CALLING_BACK_AND_FINISHED;
+ grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->error, finished_completion, w,
+ &w->completion_storage);
break;
case CALLING_BACK_AND_FINISHED:
GPR_UNREACHABLE_CODE(return );
- case CALLED_BACK:
- delete = 1;
break;
}
gpr_mu_unlock(&w->mu);
- if (delete) {
- delete_state_watcher(exec_ctx, w);
- }
-
GRPC_ERROR_UNREF(error);
}
@@ -179,6 +183,28 @@ static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw,
partly_done(exec_ctx, pw, false, GRPC_ERROR_REF(error));
}
+int grpc_channel_num_external_connectivity_watchers(grpc_channel *channel) {
+ grpc_channel_element *client_channel_elem =
+ grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
+ return grpc_client_channel_num_external_connectivity_watchers(
+ client_channel_elem);
+}
+
+typedef struct watcher_timer_init_arg {
+ state_watcher *w;
+ gpr_timespec deadline;
+} watcher_timer_init_arg;
+
+static void watcher_timer_init(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error_ignored) {
+ watcher_timer_init_arg *wa = (watcher_timer_init_arg *)arg;
+
+ grpc_timer_init(exec_ctx, &wa->w->alarm,
+ gpr_convert_clock_type(wa->deadline, GPR_CLOCK_MONOTONIC),
+ &wa->w->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC));
+ gpr_free(wa);
+}
+
void grpc_channel_watch_connectivity_state(
grpc_channel *channel, grpc_connectivity_state last_observed_state,
gpr_timespec deadline, grpc_completion_queue *cq, void *tag) {
@@ -208,16 +234,19 @@ void grpc_channel_watch_connectivity_state(
w->cq = cq;
w->tag = tag;
w->channel = channel;
+ w->error = NULL;
- grpc_timer_init(&exec_ctx, &w->alarm,
- gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
- &w->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC));
+ watcher_timer_init_arg *wa = gpr_malloc(sizeof(watcher_timer_init_arg));
+ wa->w = w;
+ wa->deadline = deadline;
+ grpc_closure_init(&w->watcher_timer_init, watcher_timer_init, wa,
+ grpc_schedule_on_exec_ctx);
if (client_channel_elem->filter == &grpc_client_channel_filter) {
GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity");
- grpc_client_channel_watch_connectivity_state(&exec_ctx, client_channel_elem,
- grpc_cq_pollset(cq), &w->state,
- &w->on_complete);
+ grpc_client_channel_watch_connectivity_state(
+ &exec_ctx, client_channel_elem, grpc_cq_pollset(cq), &w->state,
+ &w->on_complete, &w->watcher_timer_init);
} else {
abort();
}
diff --git a/src/core/ext/filters/client_channel/client_channel.c b/src/core/ext/filters/client_channel/client_channel.c
index 67b011aff37..e6740c7892d 100644
--- a/src/core/ext/filters/client_channel/client_channel.c
+++ b/src/core/ext/filters/client_channel/client_channel.c
@@ -167,6 +167,8 @@ static void *method_parameters_create_from_json(const grpc_json *json) {
return value;
}
+struct external_connectivity_watcher;
+
/*************************************************************************
* CHANNEL-WIDE FUNCTIONS
*/
@@ -204,6 +206,11 @@ typedef struct client_channel_channel_data {
/** interested parties (owned) */
grpc_pollset_set *interested_parties;
+ /* external_connectivity_watcher_list head is guarded by its own mutex, since
+ * counts need to be grabbed immediately without polling on a cq */
+ gpr_mu external_connectivity_watcher_list_mu;
+ struct external_connectivity_watcher *external_connectivity_watcher_list_head;
+
/* the following properties are guarded by a mutex since API's require them
to be instantaneously available */
gpr_mu info_mu;
@@ -661,6 +668,12 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
// Initialize data members.
chand->combiner = grpc_combiner_create();
gpr_mu_init(&chand->info_mu);
+ gpr_mu_init(&chand->external_connectivity_watcher_list_mu);
+
+ gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
+ chand->external_connectivity_watcher_list_head = NULL;
+ gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
+
chand->owning_stack = args->channel_stack;
grpc_closure_init(&chand->on_resolver_result_changed,
on_resolver_result_changed_locked, chand,
@@ -748,6 +761,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
gpr_mu_destroy(&chand->info_mu);
+ gpr_mu_destroy(&chand->external_connectivity_watcher_list_mu);
}
/*************************************************************************
@@ -1449,14 +1463,79 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
return out;
}
-typedef struct {
+typedef struct external_connectivity_watcher {
channel_data *chand;
grpc_pollset *pollset;
grpc_closure *on_complete;
+ grpc_closure *watcher_timer_init;
grpc_connectivity_state *state;
grpc_closure my_closure;
+ struct external_connectivity_watcher *next;
} external_connectivity_watcher;
+static external_connectivity_watcher *lookup_external_connectivity_watcher(
+ channel_data *chand, grpc_closure *on_complete) {
+ gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
+ external_connectivity_watcher *w =
+ chand->external_connectivity_watcher_list_head;
+ while (w != NULL && w->on_complete != on_complete) {
+ w = w->next;
+ }
+ gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
+ return w;
+}
+
+static void external_connectivity_watcher_list_append(
+ channel_data *chand, external_connectivity_watcher *w) {
+ GPR_ASSERT(!lookup_external_connectivity_watcher(chand, w->on_complete));
+
+ gpr_mu_lock(&w->chand->external_connectivity_watcher_list_mu);
+ GPR_ASSERT(!w->next);
+ w->next = chand->external_connectivity_watcher_list_head;
+ chand->external_connectivity_watcher_list_head = w;
+ gpr_mu_unlock(&w->chand->external_connectivity_watcher_list_mu);
+}
+
+static void external_connectivity_watcher_list_remove(
+ channel_data *chand, external_connectivity_watcher *too_remove) {
+ GPR_ASSERT(
+ lookup_external_connectivity_watcher(chand, too_remove->on_complete));
+ gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
+ if (too_remove == chand->external_connectivity_watcher_list_head) {
+ chand->external_connectivity_watcher_list_head = too_remove->next;
+ gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
+ return;
+ }
+ external_connectivity_watcher *w =
+ chand->external_connectivity_watcher_list_head;
+ while (w != NULL) {
+ if (w->next == too_remove) {
+ w->next = w->next->next;
+ gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
+ return;
+ }
+ w = w->next;
+ }
+ GPR_UNREACHABLE_CODE(return );
+}
+
+int grpc_client_channel_num_external_connectivity_watchers(
+ grpc_channel_element *elem) {
+ channel_data *chand = elem->channel_data;
+ int count = 0;
+
+ gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
+ external_connectivity_watcher *w =
+ chand->external_connectivity_watcher_list_head;
+ while (w != NULL) {
+ count++;
+ w = w->next;
+ }
+ gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
+
+ return count;
+}
+
static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
external_connectivity_watcher *w = arg;
@@ -1465,6 +1544,7 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
w->pollset);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
"external_connectivity_watcher");
+ external_connectivity_watcher_list_remove(w->chand, w);
gpr_free(w);
grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
}
@@ -1472,21 +1552,42 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error_ignored) {
external_connectivity_watcher *w = arg;
- grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
- grpc_schedule_on_exec_ctx);
- grpc_connectivity_state_notify_on_state_change(
- exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
+ external_connectivity_watcher *found = NULL;
+ if (w->state != NULL) {
+ external_connectivity_watcher_list_append(w->chand, w);
+ grpc_closure_run(exec_ctx, w->watcher_timer_init, GRPC_ERROR_NONE);
+ grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
+ grpc_schedule_on_exec_ctx);
+ grpc_connectivity_state_notify_on_state_change(
+ exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
+ } else {
+ GPR_ASSERT(w->watcher_timer_init == NULL);
+ found = lookup_external_connectivity_watcher(w->chand, w->on_complete);
+ if (found) {
+ GPR_ASSERT(found->on_complete == w->on_complete);
+ grpc_connectivity_state_notify_on_state_change(
+ exec_ctx, &found->chand->state_tracker, NULL, &found->my_closure);
+ }
+ grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
+ w->pollset);
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
+ "external_connectivity_watcher");
+ gpr_free(w);
+ }
}
void grpc_client_channel_watch_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
- grpc_connectivity_state *state, grpc_closure *closure) {
+ grpc_connectivity_state *state, grpc_closure *closure,
+ grpc_closure *watcher_timer_init) {
channel_data *chand = elem->channel_data;
- external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
+ external_connectivity_watcher *w = gpr_zalloc(sizeof(*w));
w->chand = chand;
w->pollset = pollset;
w->on_complete = closure;
w->state = state;
+ w->watcher_timer_init = watcher_timer_init;
+
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
"external_connectivity_watcher");
diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h
index 8d2490ea55d..356a7ab0c15 100644
--- a/src/core/ext/filters/client_channel/client_channel.h
+++ b/src/core/ext/filters/client_channel/client_channel.h
@@ -53,9 +53,13 @@ extern const grpc_channel_filter grpc_client_channel_filter;
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
+int grpc_client_channel_num_external_connectivity_watchers(
+ grpc_channel_element *elem);
+
void grpc_client_channel_watch_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
- grpc_connectivity_state *state, grpc_closure *on_complete);
+ grpc_connectivity_state *state, grpc_closure *on_complete,
+ grpc_closure *watcher_timer_init);
/* Debug helper: pull the subchannel call from a call stack element */
grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc
index 72a4c4cf94a..e4f5cb8422e 100644
--- a/src/cpp/common/version_cc.cc
+++ b/src/cpp/common/version_cc.cc
@@ -37,5 +37,5 @@
#include
namespace grpc {
-grpc::string Version() { return "1.4.0-dev"; }
+grpc::string Version() { return "1.5.0-dev"; }
}
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index c849d2e5b48..e20e9333741 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -172,8 +172,15 @@ ServerBuilder& ServerBuilder::SetResourceQuota(
}
ServerBuilder& ServerBuilder::AddListeningPort(
- const grpc::string& addr, std::shared_ptr creds,
+ const grpc::string& addr_uri, std::shared_ptr creds,
int* selected_port) {
+ const grpc::string uri_scheme = "dns:";
+ grpc::string addr = addr_uri;
+ if (addr_uri.compare(0, uri_scheme.size(), uri_scheme) == 0) {
+ size_t pos = uri_scheme.size();
+ while (addr_uri[pos] == '/') ++pos; // Skip slashes.
+ addr = addr_uri.substr(pos);
+ }
Port port = {addr, creds, selected_port};
ports_.push_back(port);
return *this;
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
index 6ac25aa1f02..188ddb95b99 100755
--- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
@@ -16,6 +16,8 @@
https://github.com/grpc/grpc
https://github.com/grpc/grpc/blob/master/LICENSE
1.6.0
+ true
+ true
@@ -23,7 +25,9 @@
-
+
+ None
+
diff --git a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj
index f4dd5105fc7..45ec8743222 100755
--- a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj
+++ b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj
@@ -1,4 +1,4 @@
-
+
@@ -16,6 +16,8 @@
https://github.com/grpc/grpc
https://github.com/grpc/grpc/blob/master/LICENSE
1.6.0
+ true
+ true
@@ -23,7 +25,9 @@
-
+
+ None
+
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index 4f29c35b321..51ae11fbdec 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -59,6 +59,8 @@ namespace Grpc.Core
readonly ChannelSafeHandle handle;
readonly Dictionary options;
+ readonly Task connectivityWatcherTask;
+
bool shutdownRequested;
///
@@ -99,6 +101,9 @@ namespace Grpc.Core
this.handle = ChannelSafeHandle.CreateInsecure(target, nativeChannelArgs);
}
}
+ // TODO(jtattermusch): Workaround for https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/822.
+ // Remove once retries are supported in C core
+ this.connectivityWatcherTask = RunConnectivityWatcherAsync();
GrpcEnvironment.RegisterChannel(this);
}
@@ -244,7 +249,7 @@ namespace Grpc.Core
handle.Dispose();
- await GrpcEnvironment.ReleaseAsync().ConfigureAwait(false);
+ await Task.WhenAll(GrpcEnvironment.ReleaseAsync(), connectivityWatcherTask).ConfigureAwait(false);
}
internal ChannelSafeHandle Handle
@@ -299,6 +304,40 @@ namespace Grpc.Core
}
}
+ ///
+ /// Constantly Watches channel connectivity status to work around https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/822
+ ///
+ private async Task RunConnectivityWatcherAsync()
+ {
+ try
+ {
+ var lastState = State;
+ while (lastState != ChannelState.Shutdown)
+ {
+ lock (myLock)
+ {
+ if (shutdownRequested)
+ {
+ break;
+ }
+ }
+
+ try
+ {
+ await WaitForStateChangedAsync(lastState, DateTime.UtcNow.AddSeconds(1)).ConfigureAwait(false);
+ }
+ catch (TaskCanceledException)
+ {
+ // ignore timeout
+ }
+ lastState = State;
+ }
+ }
+ catch (ObjectDisposedException) {
+ // during shutdown, channel is going to be disposed.
+ }
+ }
+
private static void EnsureUserAgentChannelOption(Dictionary options)
{
var key = ChannelOptions.PrimaryUserAgentString;
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index c0865001a80..ae0d8b2c8d8 100755
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -1,4 +1,4 @@
-
+
@@ -15,6 +15,8 @@
https://github.com/grpc/grpc
https://github.com/grpc/grpc/blob/master/LICENSE
1.6.0
+ true
+ true
diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include
index 8388bfd9cca..81156452f3e 100755
--- a/src/csharp/Grpc.Core/Version.csproj.include
+++ b/src/csharp/Grpc.Core/Version.csproj.include
@@ -1,7 +1,7 @@
- 1.4.0-dev
+ 1.5.0-dev
3.3.0
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index 2e55d9d80eb..d507878c2df 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -48,11 +48,11 @@ namespace Grpc.Core
///
/// Current AssemblyFileVersion of gRPC C# assemblies
///
- public const string CurrentAssemblyFileVersion = "1.4.0.0";
+ public const string CurrentAssemblyFileVersion = "1.5.0.0";
///
/// Current version of gRPC C#
///
- public const string CurrentVersion = "1.4.0-dev";
+ public const string CurrentVersion = "1.5.0-dev";
}
}
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
index eac6e1fc95f..c3791a4e6b2 100755
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -15,6 +15,8 @@
https://github.com/grpc/grpc
https://github.com/grpc/grpc/blob/master/LICENSE
1.6.0
+ true
+ true
@@ -22,7 +24,9 @@
-
+
+ None
+
diff --git a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
index 70bfcc89c5c..3a075552483 100755
--- a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
+++ b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
@@ -15,6 +15,8 @@
https://github.com/grpc/grpc
https://github.com/grpc/grpc/blob/master/LICENSE
1.6.0
+ true
+ true
@@ -22,7 +24,9 @@
-
+
+ None
+
diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat
index d823942be52..35664cc762d 100755
--- a/src/csharp/build_packages_dotnetcli.bat
+++ b/src/csharp/build_packages_dotnetcli.bat
@@ -28,7 +28,7 @@
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Current package versions
-set VERSION=1.4.0-dev
+set VERSION=1.5.0-dev
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe
@@ -51,11 +51,11 @@ powershell -Command "cp -r ..\..\platform=*\artifacts\protoc_* protoc_plugins"
@rem To be able to build, we also need to put grpc_csharp_ext to its normal location
xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\
-%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Auth --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error
%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts
diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh
index f79c97fbbcd..7dc07a220df 100755
--- a/src/csharp/build_packages_dotnetcli.sh
+++ b/src/csharp/build_packages_dotnetcli.sh
@@ -48,13 +48,13 @@ dotnet restore Grpc.sln
mkdir -p ../../libs/opt
cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
-dotnet pack --configuration Release --include-symbols --include-source Grpc.Core --output ../../../artifacts
-dotnet pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ../../../artifacts
-dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth --output ../../../artifacts
-dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts
-dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts
-
-nuget pack Grpc.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
-nuget pack Grpc.Tools.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
+dotnet pack --configuration Release Grpc.Core --output ../../../artifacts
+dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts
+dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts
+dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
+dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
+
+nuget pack Grpc.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.Tools.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts
(cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index 49179ab3596..9453000ad3f 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -508,9 +508,14 @@ void Call::DestroyCall() {
}
Call::Call(grpc_call *call)
- : wrapped_call(call), pending_batches(0), has_final_op_completed(false) {}
+ : wrapped_call(call), pending_batches(0), has_final_op_completed(false) {
+ peer = grpc_call_get_peer(call);
+}
-Call::~Call() { DestroyCall(); }
+Call::~Call() {
+ DestroyCall();
+ gpr_free(peer);
+}
void Call::Init(Local