aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD3
-rw-r--r--CMakeLists.txt35
-rw-r--r--Makefile39
-rw-r--r--binding.gyp1
-rw-r--r--build.yaml13
-rw-r--r--config.m41
-rw-r--r--config.w321
-rw-r--r--gRPC-Core.podspec5
-rwxr-xr-xgrpc.gemspec3
-rw-r--r--package.xml3
-rw-r--r--src/core/ext/census/intrusive_hash_map.c302
-rw-r--r--src/core/ext/census/intrusive_hash_map.h150
-rw-r--r--src/core/ext/census/intrusive_hash_map_internal.h46
-rw-r--r--src/core/lib/http/httpcli.c2
-rw-r--r--src/core/lib/http/httpcli_security_connector.c4
-rw-r--r--src/core/lib/security/transport/security_connector.c19
-rw-r--r--src/core/lib/security/transport/security_handshaker.c220
-rw-r--r--src/node/README.md64
-rw-r--r--src/node/index.js138
-rw-r--r--src/node/src/client.js254
-rw-r--r--src/node/src/common.js64
-rw-r--r--src/node/src/constants.js24
-rw-r--r--src/node/src/credentials.js63
-rw-r--r--src/node/src/grpc_extension.js4
-rw-r--r--src/node/src/metadata.js15
-rw-r--r--src/node/src/protobuf_js_5_common.js9
-rw-r--r--src/node/src/protobuf_js_6_common.js9
-rw-r--r--src/node/src/server.js445
-rw-r--r--src/node/test/surface_test.js8
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py1
-rw-r--r--test/core/census/intrusive_hash_map_test.c282
-rw-r--r--tools/doxygen/Doxyfile.core.internal3
-rw-r--r--tools/run_tests/generated/sources_and_headers.json22
-rw-r--r--tools/run_tests/generated/tests.json22
-rw-r--r--vsprojects/buildtests_c.sln27
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj4
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj.filters9
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj4
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters9
-rw-r--r--vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj199
-rw-r--r--vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj.filters21
41 files changed, 1998 insertions, 549 deletions
diff --git a/BUILD b/BUILD
index cc5fd3eb47..bdea522ad1 100644
--- a/BUILD
+++ b/BUILD
@@ -282,6 +282,7 @@ grpc_cc_library(
"src/core/ext/census/grpc_filter.c",
"src/core/ext/census/grpc_plugin.c",
"src/core/ext/census/initialize.c",
+ "src/core/ext/census/intrusive_hash_map.c",
"src/core/ext/census/mlog.c",
"src/core/ext/census/operation.c",
"src/core/ext/census/placeholders.c",
@@ -297,6 +298,8 @@ grpc_cc_library(
"src/core/ext/census/gen/census.pb.h",
"src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h",
+ "src/core/ext/census/intrusive_hash_map.h",
+ "src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1a23545602..1635d5dc2d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -375,6 +375,7 @@ add_dependencies(buildtests_c bdp_estimator_test)
add_dependencies(buildtests_c bin_decoder_test)
add_dependencies(buildtests_c bin_encoder_test)
add_dependencies(buildtests_c census_context_test)
+add_dependencies(buildtests_c census_intrusive_hash_map_test)
add_dependencies(buildtests_c census_resource_test)
add_dependencies(buildtests_c census_trace_context_test)
add_dependencies(buildtests_c channel_create_test)
@@ -1157,6 +1158,7 @@ add_library(grpc
src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c
+ src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
@@ -2048,6 +2050,7 @@ add_library(grpc_unsecure
src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c
+ src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
@@ -2659,6 +2662,7 @@ add_library(grpc++_cronet
src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c
+ src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
@@ -4769,6 +4773,37 @@ target_link_libraries(census_context_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
+add_executable(census_intrusive_hash_map_test
+ test/core/census/intrusive_hash_map_test.c
+)
+
+
+target_include_directories(census_intrusive_hash_map_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(census_intrusive_hash_map_test
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr_test_util
+ gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
add_executable(census_resource_test
test/core/census/resource_test.c
)
diff --git a/Makefile b/Makefile
index 5e5cd956bb..188ca8b268 100644
--- a/Makefile
+++ b/Makefile
@@ -967,6 +967,7 @@ bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
+census_intrusive_hash_map_test: $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test
census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
@@ -1360,6 +1361,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/bin_decoder_test \
$(BINDIR)/$(CONFIG)/bin_encoder_test \
$(BINDIR)/$(CONFIG)/census_context_test \
+ $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test \
$(BINDIR)/$(CONFIG)/census_resource_test \
$(BINDIR)/$(CONFIG)/census_trace_context_test \
$(BINDIR)/$(CONFIG)/channel_create_test \
@@ -1763,6 +1765,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
$(E) "[RUN] Testing census_context_test"
$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
+ $(E) "[RUN] Testing census_intrusive_hash_map_test"
+ $(Q) $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test || ( echo test census_intrusive_hash_map_test failed ; exit 1 )
$(E) "[RUN] Testing census_resource_test"
$(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 )
$(E) "[RUN] Testing census_trace_context_test"
@@ -3134,6 +3138,7 @@ LIBGRPC_SRC = \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
+ src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
@@ -3994,6 +3999,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
+ src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
@@ -4591,6 +4597,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
+ src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
@@ -8687,6 +8694,38 @@ endif
endif
+CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC = \
+ test/core/census/intrusive_hash_map_test.c \
+
+CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test: $(CENSUS_INTRUSIVE_HASH_MAP_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) $(CENSUS_INTRUSIVE_HASH_MAP_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)/census_intrusive_hash_map_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/census/intrusive_hash_map_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_census_intrusive_hash_map_test: $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
CENSUS_RESOURCE_TEST_SRC = \
test/core/census/resource_test.c \
diff --git a/binding.gyp b/binding.gyp
index 8aafdaa62b..e617485134 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -890,6 +890,7 @@
'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c',
+ 'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
diff --git a/build.yaml b/build.yaml
index 98401b84c5..d2ea16c8c2 100644
--- a/build.yaml
+++ b/build.yaml
@@ -27,6 +27,8 @@ filegroups:
- src/core/ext/census/gen/census.pb.h
- src/core/ext/census/gen/trace_context.pb.h
- src/core/ext/census/grpc_filter.h
+ - src/core/ext/census/intrusive_hash_map.h
+ - src/core/ext/census/intrusive_hash_map_internal.h
- src/core/ext/census/mlog.h
- src/core/ext/census/resource.h
- src/core/ext/census/rpc_metric_id.h
@@ -45,6 +47,7 @@ filegroups:
- src/core/ext/census/grpc_filter.c
- src/core/ext/census/grpc_plugin.c
- src/core/ext/census/initialize.c
+ - src/core/ext/census/intrusive_hash_map.c
- src/core/ext/census/mlog.c
- src/core/ext/census/operation.c
- src/core/ext/census/placeholders.c
@@ -1676,6 +1679,16 @@ targets:
- grpc
- gpr_test_util
- gpr
+- name: census_intrusive_hash_map_test
+ build: test
+ language: c
+ src:
+ - test/core/census/intrusive_hash_map_test.c
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr_test_util
+ - gpr
- name: census_resource_test
build: test
language: c
diff --git a/config.m4 b/config.m4
index ec463b2243..3b9cac1abe 100644
--- a/config.m4
+++ b/config.m4
@@ -322,6 +322,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
+ src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
diff --git a/config.w32 b/config.w32
index 0d82f9d757..7c407e848a 100644
--- a/config.w32
+++ b/config.w32
@@ -299,6 +299,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\census\\grpc_filter.c " +
"src\\core\\ext\\census\\grpc_plugin.c " +
"src\\core\\ext\\census\\initialize.c " +
+ "src\\core\\ext\\census\\intrusive_hash_map.c " +
"src\\core\\ext\\census\\mlog.c " +
"src\\core\\ext\\census\\operation.c " +
"src\\core\\ext\\census\\placeholders.c " +
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 1176a15f2b..d9de2d78a0 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -463,6 +463,8 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/census.pb.h',
'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h',
+ 'src/core/ext/census/intrusive_hash_map.h',
+ 'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h',
@@ -713,6 +715,7 @@ Pod::Spec.new do |s|
'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c',
+ 'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
@@ -946,6 +949,8 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/census.pb.h',
'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h',
+ 'src/core/ext/census/intrusive_hash_map.h',
+ 'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 32c1164456..b334efb0b5 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -379,6 +379,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/gen/census.pb.h )
s.files += %w( src/core/ext/census/gen/trace_context.pb.h )
s.files += %w( src/core/ext/census/grpc_filter.h )
+ s.files += %w( src/core/ext/census/intrusive_hash_map.h )
+ s.files += %w( src/core/ext/census/intrusive_hash_map_internal.h )
s.files += %w( src/core/ext/census/mlog.h )
s.files += %w( src/core/ext/census/resource.h )
s.files += %w( src/core/ext/census/rpc_metric_id.h )
@@ -629,6 +631,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/grpc_filter.c )
s.files += %w( src/core/ext/census/grpc_plugin.c )
s.files += %w( src/core/ext/census/initialize.c )
+ s.files += %w( src/core/ext/census/intrusive_hash_map.c )
s.files += %w( src/core/ext/census/mlog.c )
s.files += %w( src/core/ext/census/operation.c )
s.files += %w( src/core/ext/census/placeholders.c )
diff --git a/package.xml b/package.xml
index 5bcffd6eed..9179ef238c 100644
--- a/package.xml
+++ b/package.xml
@@ -393,6 +393,8 @@
<file baseinstalldir="/" name="src/core/ext/census/gen/census.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/gen/trace_context.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_filter.h" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map.h" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
@@ -643,6 +645,7 @@
<file baseinstalldir="/" name="src/core/ext/census/grpc_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_plugin.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/initialize.c" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/mlog.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" />
diff --git a/src/core/ext/census/intrusive_hash_map.c b/src/core/ext/census/intrusive_hash_map.c
new file mode 100644
index 0000000000..e64e8086ca
--- /dev/null
+++ b/src/core/ext/census/intrusive_hash_map.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/core/ext/census/intrusive_hash_map.h"
+#include <string.h>
+
+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) {
+ return (uint32_t)key;
+}
+
+/* Vector chunks are 1MiB divided by pointer size. */
+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) {
+ if (index < VECTOR_CHUNK_SIZE) {
+ return &buckets->first_[index];
+ }
+ size_t rest_index = (index - VECTOR_CHUNK_SIZE) / VECTOR_CHUNK_SIZE;
+ return &buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE];
+}
+
+static inline void *get_bucket(const chunked_vector *buckets, uint32_t index) {
+ if (index < VECTOR_CHUNK_SIZE) {
+ return buckets->first_[index];
+ }
+ size_t rest_index = (index - VECTOR_CHUNK_SIZE) / VECTOR_CHUNK_SIZE;
+ return buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE];
+}
+
+/* Helper function. */
+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;
+}
+
+/* Initialize chunked vector to size of 0. */
+static void chunked_vector_init(chunked_vector *vec) {
+ vec->size_ = 0;
+ vec->first_ = NULL;
+ vec->rest_ = NULL;
+}
+
+/* Clear chunked vector and free all memory that has been allocated then
+ initialize chunked vector. */
+static void chunked_vector_clear(chunked_vector *vec) {
+ if (vec->first_ != NULL) {
+ gpr_free(vec->first_);
+ }
+ if (vec->rest_ != NULL) {
+ size_t rest_size = RestSize(vec);
+ for (size_t i = 0; i < rest_size; ++i) {
+ if (vec->rest_[i] != NULL) {
+ gpr_free(vec->rest_[i]);
+ }
+ }
+ gpr_free(vec->rest_);
+ }
+ chunked_vector_init(vec);
+}
+
+/* Clear chunked vector and then resize it to n entries. Allow the first 1MB to
+ be read w/o an extra cache miss. The rest of the elements are stored in an
+ array of arrays to avoid large mallocs. */
+static void chunked_vector_reset(chunked_vector *vec, size_t n) {
+ chunked_vector_clear(vec);
+ vec->size_ = n;
+ if (n <= VECTOR_CHUNK_SIZE) {
+ vec->first_ = (void **)gpr_malloc(sizeof(void *) * n);
+ memset(vec->first_, 0, sizeof(void *) * n);
+ } else {
+ vec->first_ = (void **)gpr_malloc(sizeof(void *) * VECTOR_CHUNK_SIZE);
+ memset(vec->first_, 0, sizeof(void *) * VECTOR_CHUNK_SIZE);
+ size_t rest_size = RestSize(vec);
+ vec->rest_ = (void ***)gpr_malloc(sizeof(void **) * rest_size);
+ memset(vec->rest_, 0, sizeof(void **) * rest_size);
+ int i = 0;
+ n -= VECTOR_CHUNK_SIZE;
+ while (n > 0) {
+ size_t this_size = GPR_MIN(n, VECTOR_CHUNK_SIZE);
+ vec->rest_[i] = (void **)gpr_malloc(sizeof(void *) * this_size);
+ memset(vec->rest_[i], 0, sizeof(void *) * this_size);
+ n -= this_size;
+ ++i;
+ }
+ }
+}
+
+void intrusive_hash_map_init(intrusive_hash_map *hash_map,
+ uint32_t initial_log2_table_size) {
+ hash_map->log2_num_buckets = initial_log2_table_size;
+ hash_map->num_items = 0;
+ uint32_t num_buckets = (uint32_t)1 << hash_map->log2_num_buckets;
+ hash_map->extend_threshold = num_buckets >> 1;
+ chunked_vector_init(&hash_map->buckets);
+ chunked_vector_reset(&hash_map->buckets, num_buckets);
+ hash_map->hash_mask = num_buckets - 1;
+}
+
+bool intrusive_hash_map_empty(const intrusive_hash_map *hash_map) {
+ return hash_map->num_items == 0;
+}
+
+size_t intrusive_hash_map_size(const intrusive_hash_map *hash_map) {
+ return hash_map->num_items;
+}
+
+void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx) {
+ idx->bucket_index = (uint32_t)hash_map->buckets.size_;
+ GPR_ASSERT(idx->bucket_index <= UINT32_MAX);
+ idx->item = NULL;
+}
+
+void intrusive_hash_map_next(const intrusive_hash_map *hash_map,
+ hm_index *idx) {
+ idx->item = idx->item->hash_link;
+ while (idx->item == NULL) {
+ idx->bucket_index++;
+ if (idx->bucket_index >= hash_map->buckets.size_) {
+ /* Reached end of table. */
+ idx->item = NULL;
+ return;
+ }
+ idx->item = (hm_item *)get_bucket(&hash_map->buckets, idx->bucket_index);
+ }
+}
+
+void intrusive_hash_map_begin(const intrusive_hash_map *hash_map,
+ hm_index *idx) {
+ for (uint32_t i = 0; i < hash_map->buckets.size_; ++i) {
+ if (get_bucket(&hash_map->buckets, i) != NULL) {
+ idx->bucket_index = i;
+ idx->item = (hm_item *)get_bucket(&hash_map->buckets, i);
+ return;
+ }
+ }
+ intrusive_hash_map_end(hash_map, idx);
+}
+
+hm_item *intrusive_hash_map_find(const intrusive_hash_map *hash_map,
+ uint64_t key) {
+ uint32_t index = chunked_vector_hasher(key) & hash_map->hash_mask;
+
+ hm_item *p = (hm_item *)get_bucket(&hash_map->buckets, index);
+ while (p != NULL) {
+ if (key == p->key) {
+ return p;
+ }
+ p = p->hash_link;
+ }
+ return NULL;
+}
+
+hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key) {
+ uint32_t index = chunked_vector_hasher(key) & hash_map->hash_mask;
+
+ hm_item **slot = (hm_item **)get_mutable_bucket(&hash_map->buckets, index);
+ hm_item *p = *slot;
+ if (p == NULL) {
+ return NULL;
+ }
+
+ if (key == p->key) {
+ *slot = p->hash_link;
+ p->hash_link = NULL;
+ hash_map->num_items--;
+ return p;
+ }
+
+ hm_item *prev = p;
+ p = p->hash_link;
+
+ while (p) {
+ if (key == p->key) {
+ prev->hash_link = p->hash_link;
+ p->hash_link = NULL;
+ hash_map->num_items--;
+ return p;
+ }
+ prev = p;
+ p = p->hash_link;
+ }
+ return NULL;
+}
+
+/* Insert an hm_item* into the underlying chunked vector. hash_mask is
+ * 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) {
+ 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);
+ hm_item *p = *slot;
+ item->hash_link = p;
+
+ /* Check to see if key already exists. */
+ while (p) {
+ if (p->key == key) {
+ return false;
+ }
+ p = p->hash_link;
+ }
+
+ /* Otherwise add new entry. */
+ *slot = item;
+ return true;
+}
+
+/* Extend the allocated number of elements in the hash map by a factor of 2. */
+void intrusive_hash_map_extend(intrusive_hash_map *hash_map) {
+ uint32_t new_log2_num_buckets = 1 + hash_map->log2_num_buckets;
+ uint32_t new_num_buckets = (uint32_t)1 << new_log2_num_buckets;
+ GPR_ASSERT(new_num_buckets <= UINT32_MAX && new_num_buckets > 0);
+ chunked_vector new_buckets;
+ chunked_vector_init(&new_buckets);
+ chunked_vector_reset(&new_buckets, new_num_buckets);
+ uint32_t new_hash_mask = new_num_buckets - 1;
+
+ hm_index cur_idx;
+ hm_index end_idx;
+ intrusive_hash_map_end(hash_map, &end_idx);
+ intrusive_hash_map_begin(hash_map, &cur_idx);
+ while (!hm_index_compare(&cur_idx, &end_idx)) {
+ hm_item *new_item = cur_idx.item;
+ intrusive_hash_map_next(hash_map, &cur_idx);
+ intrusive_hash_map_internal_insert(&new_buckets, new_hash_mask, new_item);
+ }
+
+ /* Set values for new chunked_vector. extend_threshold is set to half of
+ * new_num_buckets. */
+ hash_map->log2_num_buckets = new_log2_num_buckets;
+ chunked_vector_clear(&hash_map->buckets);
+ hash_map->buckets = new_buckets;
+ hash_map->hash_mask = new_hash_mask;
+ hash_map->extend_threshold = new_num_buckets >> 1;
+}
+
+/* Insert a hm_item. The hm_item must remain live until it is removed from the
+ table. This object does not take the ownership of hm_item. The caller must
+ remove this hm_item from the table and delete it before this table is
+ deleted. If hm_item exists already num_items is not changed. */
+bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item) {
+ if (hash_map->num_items >= hash_map->extend_threshold) {
+ intrusive_hash_map_extend(hash_map);
+ }
+ if (intrusive_hash_map_internal_insert(&hash_map->buckets,
+ hash_map->hash_mask, item)) {
+ hash_map->num_items++;
+ return true;
+ }
+ return false;
+}
+
+void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
+ void (*free_object)(void *)) {
+ hm_index cur;
+ hm_index end;
+ intrusive_hash_map_end(hash_map, &end);
+ intrusive_hash_map_begin(hash_map, &cur);
+
+ while (!hm_index_compare(&cur, &end)) {
+ hm_index next = cur;
+ intrusive_hash_map_next(hash_map, &next);
+ if (cur.item != NULL) {
+ hm_item *item = intrusive_hash_map_erase(hash_map, cur.item->key);
+ (*free_object)((void *)item);
+ gpr_free(item);
+ }
+ cur = next;
+ }
+}
+
+void intrusive_hash_map_free(intrusive_hash_map *hash_map,
+ void (*free_object)(void *)) {
+ intrusive_hash_map_clear(hash_map, (*free_object));
+ hash_map->num_items = 0;
+ hash_map->extend_threshold = 0;
+ hash_map->log2_num_buckets = 0;
+ hash_map->hash_mask = 0;
+ chunked_vector_clear(&hash_map->buckets);
+}
diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h
new file mode 100644
index 0000000000..9a7fd07f20
--- /dev/null
+++ b/src/core/ext/census/intrusive_hash_map.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
+#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
+
+#include "src/core/ext/census/intrusive_hash_map_internal.h"
+
+/* intrusive_hash_map is a fast chained hash table. This hash map is faster than
+ * a dense hash map when the application calls insert and erase more often than
+ * find. When the workload is dominated by find() a dense hash map may be
+ * faster.
+ *
+ * intrusive_hash_map uses an intrusive header placed within a user defined
+ * struct. The header field IHM_key MUST be set to a valid value before
+ * insertion into the hash map or undefined behavior may occur. The header field
+ * IHM_hash_link MUST to be set to NULL initially.
+ *
+ * EXAMPLE USAGE:
+ *
+ * typedef struct string_item {
+ * INTRUSIVE_HASH_MAP_HEADER;
+ * // User data.
+ * char *str_buf;
+ * uint16_t len;
+ * } string_item;
+ *
+ * static string_item *make_string_item(uint64_t key, const char *buf,
+ * uint16_t len) {
+ * string_item *item = (string_item *)gpr_malloc(sizeof(string_item));
+ * item->IHM_key = key;
+ * item->IHM_hash_link = NULL;
+ * item->len = len;
+ * item->str_buf = (char *)malloc(len);
+ * memcpy(item->str_buf, buf, len);
+ * return item;
+ * }
+ *
+ * intrusive_hash_map hash_map;
+ * intrusive_hash_map_init(&hash_map, 4);
+ * string_item *new_item1 = make_string_item(10, "test1", 5);
+ * bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1);
+ *
+ * string_item *item1 =
+ * (string_item *)intrusive_hash_map_find(&hash_map, 10);
+ */
+
+/* Hash map item. Stores key and a pointer to the actual object. A user defined
+ * version of this can be passed in provided the first 2 entries (key and
+ * hash_link) are the same. These entries must be first in the user defined
+ * struct. Pointer to struct will need to be cast as (hm_item *) when passed to
+ * hash map. This allows it to be intrusive. */
+typedef struct hm_item {
+ uint64_t key;
+ struct hm_item *hash_link;
+ /* Optional user defined data after this. */
+} hm_item;
+
+/* Macro provided for ease of use. This must be first in the user defined
+ * struct (i.e. uint64_t key and hm_item * must be the first two elements in
+ * that order). */
+#define INTRUSIVE_HASH_MAP_HEADER \
+ uint64_t IHM_key; \
+ struct hm_item *IHM_hash_link
+
+/* Index struct which acts as a pseudo-iterator within the hash map. */
+typedef struct hm_index {
+ uint32_t bucket_index; // hash map bucket index.
+ hm_item *item; // Pointer to hm_item within the hash map.
+} 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) {
+ return (A->item == B->item && A->bucket_index == B->bucket_index);
+}
+
+/*
+ * Helper functions for iterating over the hash map.
+ */
+
+/* On return idx will contain an invalid index which is always equal to
+ * hash_map->buckets.size_ */
+void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx);
+
+/* Iterates index to the next valid entry in the hash map and stores the
+ * index within idx. If end of table is reached, idx will contain the same
+ * values as if intrusive_hash_map_end() was called. */
+void intrusive_hash_map_next(const intrusive_hash_map *hash_map, hm_index *idx);
+
+/* On return, idx will contain the index of the first non-null entry in the hash
+ * map. If the hash map is empty, idx will contain the same values as if
+ * intrusive_hash_map_end() was called. */
+void intrusive_hash_map_begin(const intrusive_hash_map *hash_map,
+ hm_index *idx);
+
+/* Initialize intrusive hash map data structure. This must be called before
+ * the hash map can be used. The initial size of an intrusive hash map will be
+ * 2^initial_log2_map_size (valid range is [0, 31]). */
+void intrusive_hash_map_init(intrusive_hash_map *hash_map,
+ uint32_t initial_log2_map_size);
+
+/* Returns true if the hash map is empty and false otherwise. */
+bool intrusive_hash_map_empty(const intrusive_hash_map *hash_map);
+
+/* Returns the number of elements currently in the hash map. */
+size_t intrusive_hash_map_size(const intrusive_hash_map *hash_map);
+
+/* Find a hm_item within the hash map by key. Returns NULL if item was not
+ * found. */
+hm_item *intrusive_hash_map_find(const intrusive_hash_map *hash_map,
+ uint64_t key);
+
+/* Erase the hm_item that corresponds with key. If the hm_item is found, return
+ * the pointer to the hm_item. Else returns NULL. */
+hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key);
+
+/* Attempts to insert a new hm_item into the hash map. If an element with the
+ * same key already exists, it will not insert the new item and return false.
+ * Otherwise, it will insert the new item and return true. */
+bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item);
+
+/* Clears entire contents of the hash map, but leaves internal data structure
+ * untouched. Second argument takes a function pointer to a function that will
+ * free the object designated by the user and pointed to by hash_map->value. */
+void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
+ void (*free_object)(void *));
+
+/* Erase all contents of hash map and free the memory. Hash map is invalid
+ * after calling this function and cannot be used until it has been
+ * reinitialized (intrusive_hash_map_init()). This function takes a function
+ * pointer to a function that will free the object designated by the user and
+ * pointed to by hash_map->value. */
+void intrusive_hash_map_free(intrusive_hash_map *hash_map,
+ void (*free_object)(void *));
+
+#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
diff --git a/src/core/ext/census/intrusive_hash_map_internal.h b/src/core/ext/census/intrusive_hash_map_internal.h
new file mode 100644
index 0000000000..c0a3c6f59a
--- /dev/null
+++ b/src/core/ext/census/intrusive_hash_map_internal.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
+#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+#include <stdbool.h>
+
+/* The chunked vector is a data structure that allocates buckets for use in the
+ * hash map. ChunkedVector is logically equivalent to T*[N] (cast void* as
+ * T*). It's internally implemented as an array of 1MB arrays to avoid
+ * allocating large consecutive memory chunks. This is an internal data
+ * structure that should never be accessed directly. */
+typedef struct chunked_vector {
+ size_t size_;
+ void **first_;
+ void ***rest_;
+} chunked_vector;
+
+/* Core intrusive hash map data structure. All internal elements are managed by
+ * functions and should not be altered manually. */
+typedef struct intrusive_hash_map {
+ uint32_t num_items;
+ uint32_t extend_threshold;
+ uint32_t log2_num_buckets;
+ uint32_t hash_mask;
+ chunked_vector buckets;
+} intrusive_hash_map;
+
+#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c
index c3421e1b55..f5588a9a76 100644
--- a/src/core/lib/http/httpcli.c
+++ b/src/core/lib/http/httpcli.c
@@ -245,7 +245,7 @@ static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
internal_request *req = arg;
if (error != GRPC_ERROR_NONE) {
- finish(exec_ctx, req, error);
+ finish(exec_ctx, req, GRPC_ERROR_REF(error));
return;
}
req->next_address = 0;
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
index 76946434f0..ea7c1122c1 100644
--- a/src/core/lib/http/httpcli_security_connector.c
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -44,6 +44,7 @@
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/tsi/ssl_transport_security.h"
+#include "src/core/tsi/transport_security_adapter.h"
typedef struct {
grpc_channel_security_connector base;
@@ -78,7 +79,8 @@ static void httpcli_ssl_add_handshakers(grpc_exec_ctx *exec_ctx,
}
grpc_handshake_manager_add(
handshake_mgr,
- grpc_security_handshaker_create(exec_ctx, handshaker, &sc->base));
+ grpc_security_handshaker_create(
+ exec_ctx, tsi_create_adapter_handshaker(handshaker), &sc->base));
}
static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 30431a4e4a..416a3bdb35 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -56,6 +56,7 @@
#include "src/core/lib/support/string.h"
#include "src/core/tsi/fake_transport_security.h"
#include "src/core/tsi/ssl_transport_security.h"
+#include "src/core/tsi/transport_security_adapter.h"
/* -- Constants. -- */
@@ -390,7 +391,8 @@ static void fake_channel_add_handshakers(
grpc_handshake_manager_add(
handshake_mgr,
grpc_security_handshaker_create(
- exec_ctx, tsi_create_fake_handshaker(true /* is_client */),
+ exec_ctx, tsi_create_adapter_handshaker(
+ tsi_create_fake_handshaker(true /* is_client */)),
&sc->base));
}
@@ -400,7 +402,8 @@ static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx,
grpc_handshake_manager_add(
handshake_mgr,
grpc_security_handshaker_create(
- exec_ctx, tsi_create_fake_handshaker(false /* is_client */),
+ exec_ctx, tsi_create_adapter_handshaker(
+ tsi_create_fake_handshaker(false /* is_client */)),
&sc->base));
}
@@ -495,8 +498,10 @@ static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx,
}
// Create handshakers.
- grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
- exec_ctx, tsi_hs, &sc->base));
+ grpc_handshake_manager_add(
+ handshake_mgr,
+ grpc_security_handshaker_create(
+ exec_ctx, tsi_create_adapter_handshaker(tsi_hs), &sc->base));
}
static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx,
@@ -515,8 +520,10 @@ static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx,
}
// Create handshakers.
- grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
- exec_ctx, tsi_hs, &sc->base));
+ grpc_handshake_manager_add(
+ handshake_mgr,
+ grpc_security_handshaker_create(
+ exec_ctx, tsi_create_adapter_handshaker(tsi_hs), &sc->base));
}
static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {
diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c
index 509b4b556d..3bc113e20f 100644
--- a/src/core/lib/security/transport/security_handshaker.c
+++ b/src/core/lib/security/transport/security_handshaker.c
@@ -71,12 +71,12 @@ typedef struct {
unsigned char *handshake_buffer;
size_t handshake_buffer_size;
- grpc_slice_buffer left_overs;
grpc_slice_buffer outgoing;
grpc_closure on_handshake_data_sent_to_peer;
grpc_closure on_handshake_data_received_from_peer;
grpc_closure on_peer_checked;
grpc_auth_context *auth_context;
+ tsi_handshaker_result *handshaker_result;
} security_handshaker;
static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
@@ -84,6 +84,7 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
if (gpr_unref(&h->refs)) {
gpr_mu_destroy(&h->mu);
tsi_handshaker_destroy(h->handshaker);
+ tsi_handshaker_result_destroy(h->handshaker_result);
if (h->endpoint_to_destroy != NULL) {
grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy);
}
@@ -92,7 +93,6 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
gpr_free(h->read_buffer_to_destroy);
}
gpr_free(h->handshake_buffer);
- grpc_slice_buffer_destroy_internal(exec_ctx, &h->left_overs);
grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing);
GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake");
@@ -150,10 +150,10 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error));
goto done;
}
- // Get frame protector.
+ // Create frame protector.
tsi_frame_protector *protector;
- tsi_result result =
- tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
+ tsi_result result = tsi_handshaker_result_create_frame_protector(
+ h->handshaker_result, NULL, &protector);
if (result != TSI_OK) {
error = grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Frame protector creation failed"),
@@ -161,14 +161,25 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
security_handshake_failed_locked(exec_ctx, h, error);
goto done;
}
- // Success.
+ // Get unused bytes.
+ unsigned char *unused_bytes = NULL;
+ size_t unused_bytes_size = 0;
+ result = tsi_handshaker_result_get_unused_bytes(
+ h->handshaker_result, &unused_bytes, &unused_bytes_size);
// Create secure endpoint.
- h->args->endpoint = grpc_secure_endpoint_create(
- protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count);
- h->left_overs.count = 0;
- h->left_overs.length = 0;
- // Clear out the read buffer before it gets passed to the transport,
- // since any excess bytes were already copied to h->left_overs.
+ if (unused_bytes_size > 0) {
+ grpc_slice slice =
+ grpc_slice_from_copied_buffer((char *)unused_bytes, unused_bytes_size);
+ h->args->endpoint =
+ grpc_secure_endpoint_create(protector, h->args->endpoint, &slice, 1);
+ grpc_slice_unref_internal(exec_ctx, slice);
+ } else {
+ h->args->endpoint =
+ grpc_secure_endpoint_create(protector, h->args->endpoint, NULL, 0);
+ }
+ tsi_handshaker_result_destroy(h->handshaker_result);
+ h->handshaker_result = NULL;
+ // Clear out the read buffer before it gets passed to the transport.
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer);
// Add auth context to channel args.
grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context);
@@ -189,7 +200,8 @@ done:
static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
security_handshaker *h) {
tsi_peer peer;
- tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
+ tsi_result result =
+ tsi_handshaker_result_extract_peer(h->handshaker_result, &peer);
if (result != TSI_OK) {
return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result);
@@ -199,34 +211,87 @@ static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_NONE;
}
-static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx,
- security_handshaker *h) {
- // Get data to send.
- tsi_result result = TSI_OK;
- size_t offset = 0;
- do {
- size_t to_send_size = h->handshake_buffer_size - offset;
- result = tsi_handshaker_get_bytes_to_send_to_peer(
- h->handshaker, h->handshake_buffer + offset, &to_send_size);
- offset += to_send_size;
- if (result == TSI_INCOMPLETE_DATA) {
- h->handshake_buffer_size *= 2;
- h->handshake_buffer =
- gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
- }
- } while (result == TSI_INCOMPLETE_DATA);
+static grpc_error *on_handshake_next_done_locked(
+ grpc_exec_ctx *exec_ctx, security_handshaker *h, tsi_result result,
+ const unsigned char *bytes_to_send, size_t bytes_to_send_size,
+ tsi_handshaker_result *handshaker_result) {
+ grpc_error *error = GRPC_ERROR_NONE;
+ // Read more if we need to.
+ if (result == TSI_INCOMPLETE_DATA) {
+ GPR_ASSERT(bytes_to_send_size == 0);
+ grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
+ &h->on_handshake_data_received_from_peer);
+ return error;
+ }
if (result != TSI_OK) {
return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result);
}
- // Send data.
- grpc_slice to_send =
- grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
- grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
- grpc_slice_buffer_add(&h->outgoing, to_send);
- grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
- &h->on_handshake_data_sent_to_peer);
- return GRPC_ERROR_NONE;
+ // Update handshaker result.
+ if (handshaker_result != NULL) {
+ GPR_ASSERT(h->handshaker_result == NULL);
+ h->handshaker_result = handshaker_result;
+ }
+ if (bytes_to_send_size > 0) {
+ // Send data to peer, if needed.
+ grpc_slice to_send = grpc_slice_from_copied_buffer(
+ (const char *)bytes_to_send, bytes_to_send_size);
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
+ grpc_slice_buffer_add(&h->outgoing, to_send);
+ grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
+ &h->on_handshake_data_sent_to_peer);
+ } else if (handshaker_result == NULL) {
+ // There is nothing to send, but need to read from peer.
+ grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
+ &h->on_handshake_data_received_from_peer);
+ } else {
+ // Handshake has finished, check peer and so on.
+ error = check_peer_locked(exec_ctx, h);
+ }
+ return error;
+}
+
+static void on_handshake_next_done_grpc_wrapper(
+ tsi_result result, void *user_data, const unsigned char *bytes_to_send,
+ size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) {
+ security_handshaker *h = user_data;
+ // This callback will be invoked by TSI in a non-grpc thread, so it's
+ // safe to create our own exec_ctx here.
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ gpr_mu_lock(&h->mu);
+ grpc_error *error =
+ on_handshake_next_done_locked(&exec_ctx, h, result, bytes_to_send,
+ bytes_to_send_size, handshaker_result);
+ if (error != GRPC_ERROR_NONE) {
+ security_handshake_failed_locked(&exec_ctx, h, error);
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(&exec_ctx, h);
+ } else {
+ gpr_mu_unlock(&h->mu);
+ }
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static grpc_error *do_handshaker_next_locked(
+ grpc_exec_ctx *exec_ctx, security_handshaker *h,
+ const unsigned char *bytes_received, size_t bytes_received_size) {
+ // Invoke TSI handshaker.
+ unsigned char *bytes_to_send = NULL;
+ size_t bytes_to_send_size = 0;
+ tsi_handshaker_result *handshaker_result = NULL;
+ tsi_result result = tsi_handshaker_next(
+ h->handshaker, bytes_received, bytes_received_size, &bytes_to_send,
+ &bytes_to_send_size, &handshaker_result,
+ &on_handshake_next_done_grpc_wrapper, h);
+ if (result == TSI_ASYNC) {
+ // Handshaker operating asynchronously. Nothing else to do here;
+ // callback will be invoked in a TSI thread.
+ return GRPC_ERROR_NONE;
+ }
+ // Handshaker returned synchronously. Invoke callback directly in
+ // this thread with our existing exec_ctx.
+ return on_handshake_next_done_locked(exec_ctx, h, result, bytes_to_send,
+ bytes_to_send_size, handshaker_result);
}
static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
@@ -241,72 +306,34 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
security_handshaker_unref(exec_ctx, h);
return;
}
- // Process received data.
- tsi_result result = TSI_OK;
- size_t consumed_slice_size = 0;
+ // Copy all slices received.
size_t i;
+ size_t bytes_received_size = 0;
for (i = 0; i < h->args->read_buffer->count; i++) {
- consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
- result = tsi_handshaker_process_bytes_from_peer(
- h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]),
- &consumed_slice_size);
- if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
+ bytes_received_size += GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
}
- if (tsi_handshaker_is_in_progress(h->handshaker)) {
- /* We may need more data. */
- if (result == TSI_INCOMPLETE_DATA) {
- grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
- &h->on_handshake_data_received_from_peer);
- goto done;
- } else {
- error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
- if (error != GRPC_ERROR_NONE) {
- security_handshake_failed_locked(exec_ctx, h, error);
- gpr_mu_unlock(&h->mu);
- security_handshaker_unref(exec_ctx, h);
- return;
- }
- goto done;
- }
+ if (bytes_received_size > h->handshake_buffer_size) {
+ h->handshake_buffer = gpr_realloc(h->handshake_buffer, bytes_received_size);
+ h->handshake_buffer_size = bytes_received_size;
}
- if (result != TSI_OK) {
- security_handshake_failed_locked(
- exec_ctx, h,
- grpc_set_tsi_error_result(
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result));
- gpr_mu_unlock(&h->mu);
- security_handshaker_unref(exec_ctx, h);
- return;
- }
- /* Handshake is done and successful this point. */
- bool has_left_overs_in_current_slice =
- (consumed_slice_size <
- GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]));
- size_t num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) +
- h->args->read_buffer->count - i - 1;
- if (num_left_overs > 0) {
- /* Put the leftovers in our buffer (ownership transfered). */
- if (has_left_overs_in_current_slice) {
- grpc_slice tail = grpc_slice_split_tail(&h->args->read_buffer->slices[i],
- consumed_slice_size);
- grpc_slice_buffer_add(&h->left_overs, tail);
- /* split_tail above increments refcount. */
- grpc_slice_unref_internal(exec_ctx, tail);
- }
- grpc_slice_buffer_addn(
- &h->left_overs, &h->args->read_buffer->slices[i + 1],
- num_left_overs - (size_t)has_left_overs_in_current_slice);
+ size_t offset = 0;
+ for (i = 0; i < h->args->read_buffer->count; i++) {
+ size_t slice_size = GPR_SLICE_LENGTH(h->args->read_buffer->slices[i]);
+ memcpy(h->handshake_buffer + offset,
+ GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), slice_size);
+ offset += slice_size;
}
- // Check peer.
- error = check_peer_locked(exec_ctx, h);
+ // Call TSI handshaker.
+ error = do_handshaker_next_locked(exec_ctx, h, h->handshake_buffer,
+ bytes_received_size);
+
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
security_handshaker_unref(exec_ctx, h);
- return;
+ } else {
+ gpr_mu_unlock(&h->mu);
}
-done:
- gpr_mu_unlock(&h->mu);
}
static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
@@ -321,8 +348,8 @@ static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
security_handshaker_unref(exec_ctx, h);
return;
}
- /* We may be done. */
- if (tsi_handshaker_is_in_progress(h->handshaker)) {
+ // We may be done.
+ if (h->handshaker_result == NULL) {
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer);
} else {
@@ -371,7 +398,7 @@ static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
h->args = args;
h->on_handshake_done = on_handshake_done;
gpr_ref(&h->refs);
- grpc_error *error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
+ grpc_error *error = do_handshaker_next_locked(exec_ctx, h, NULL, 0);
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
@@ -404,7 +431,6 @@ static grpc_handshaker *security_handshaker_create(
grpc_schedule_on_exec_ctx);
grpc_closure_init(&h->on_peer_checked, on_peer_checked, h,
grpc_schedule_on_exec_ctx);
- grpc_slice_buffer_init(&h->left_overs);
grpc_slice_buffer_init(&h->outgoing);
return &h->base;
}
diff --git a/src/node/README.md b/src/node/README.md
index 4b906643bc..3b98b97879 100644
--- a/src/node/README.md
+++ b/src/node/README.md
@@ -2,9 +2,9 @@
# Node.js gRPC Library
## PREREQUISITES
-- `node`: This requires `node` to be installed, version `0.12` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
+- `node`: This requires `node` to be installed, version `4.0` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
-- **Note:** If you installed `node` via a package manager and the version is still less than `0.12`, try directly installing it from [nodejs.org](https://nodejs.org).
+- **Note:** If you installed `node` via a package manager and the version is still less than `4.0`, try directly installing it from [nodejs.org](https://nodejs.org).
## INSTALLATION
@@ -16,7 +16,7 @@ npm install grpc
## BUILD FROM SOURCE
1. Clone [the grpc Git Repository](https://github.com/grpc/grpc).
- 2. Run `npm install` from the repository root.
+ 2. Run `npm install --build-from-source` from the repository root.
- **Note:** On Windows, this might fail due to [nodejs issue #4932](https://github.com/nodejs/node/issues/4932) in which case, you will see something like the following in `npm install`'s output (towards the very beginning):
@@ -34,61 +34,3 @@ npm install grpc
## TESTING
To run the test suite, simply run `npm test` in the install location.
-
-## API
-This library internally uses [ProtoBuf.js](https://github.com/dcodeIO/ProtoBuf.js), and some structures it exports match those exported by that library.
-
-If you require this module, you will get an object with the following members
-
-```javascript
-function load(filename)
-```
-
-Takes a filename of a [Protocol Buffer](https://developers.google.com/protocol-buffers/) file, and returns an object representing the structure of the protocol buffer in the following way:
-
- - Namespaces become maps from the names of their direct members to those member objects
- - Service definitions become client constructors for clients for that service. They also have a `service` member that can be used for constructing servers.
- - Message definitions become Message constructors like those that ProtoBuf.js would create
- - Enum definitions become Enum objects like those that ProtoBuf.js would create
- - Anything else becomes the relevant reflection object that ProtoBuf.js would create
-
-
-```javascript
-function loadObject(reflectionObject)
-```
-
-Returns the same structure that `load` returns, but takes a reflection object from `ProtoBuf.js` instead of a file name.
-
-```javascript
-function Server([serverOptions])
-```
-
-Constructs a server to which service/implementation pairs can be added.
-
-
-```javascript
-status
-```
-
-An object mapping status names to status code numbers.
-
-
-```javascript
-callError
-```
-
-An object mapping call error names to codes. This is primarily useful for tracking down certain kinds of internal errors.
-
-
-```javascript
-Credentials
-```
-
-An object with factory methods for creating credential objects for clients.
-
-
-```javascript
-ServerCredentials
-```
-
-An object with factory methods for creating credential objects for servers.
diff --git a/src/node/index.js b/src/node/index.js
index 2da77c3eae..177628e22d 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@@ -31,10 +31,6 @@
*
*/
-/**
- * @module
- */
-
'use strict';
var path = require('path');
@@ -64,24 +60,30 @@ var constants = require('./src/constants.js');
grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii'));
/**
- * Load a ProtoBuf.js object as a gRPC object. The options object can provide
- * the following options:
- * - binaryAsBase64: deserialize bytes values as base64 strings instead of
- * Buffers. Defaults to false
- * - longsAsStrings: deserialize long values as strings instead of objects.
- * Defaults to true
- * - deprecatedArgumentOrder: Use the beta method argument order for client
- * methods, with optional arguments after the callback. Defaults to false.
- * This option is only a temporary stopgap measure to smooth an API breakage.
- * It is deprecated, and new code should not use it.
- * - protobufjsVersion: Available values are 5, 6, and 'detect'. 5 and 6
- * respectively indicate that an object from the corresponding version of
- * ProtoBuf.js is provided in the value argument. If the option is 'detect',
- * gRPC will guess what the version is based on the structure of the value.
- * Defaults to 'detect'.
+ * @namespace grpc
+ */
+
+/**
+ * Load a ProtoBuf.js object as a gRPC object.
+ * @memberof grpc
+ * @alias grpc.loadObject
* @param {Object} value The ProtoBuf.js reflection object to load
* @param {Object=} options Options to apply to the loaded file
- * @return {Object<string, *>} The resulting gRPC object
+ * @param {bool=} [options.binaryAsBase64=false] deserialize bytes values as
+ * base64 strings instead of Buffers
+ * @param {bool=} [options.longsAsStrings=true] deserialize long values as
+ * strings instead of objects
+ * @param {bool=} [options.enumsAsStrings=true] deserialize enum values as
+ * strings instead of numbers. Only works with Protobuf.js 6 values.
+ * @param {bool=} [options.deprecatedArgumentOrder=false] use the beta method
+ * argument order for client methods, with optional arguments after the
+ * callback. This option is only a temporary stopgap measure to smooth an
+ * API breakage. It is deprecated, and new code should not use it.
+ * @param {(number|string)=} [options.protobufjsVersion='detect'] 5 and 6
+ * respectively indicate that an object from the corresponding version of
+ * Protobuf.js is provided in the value argument. If the option is 'detect',
+ * gRPC wll guess what the version is based on the structure of the value.
+ * @return {Object<string, *>} The resulting gRPC object.
*/
exports.loadObject = function loadObject(value, options) {
options = _.defaults(options, common.defaultGrpcOptions);
@@ -112,22 +114,23 @@ exports.loadObject = function loadObject(value, options) {
var loadObject = exports.loadObject;
/**
- * Load a gRPC object from a .proto file. The options object can provide the
- * following options:
- * - convertFieldsToCamelCase: Load this file with field names in camel case
- * instead of their original case
- * - binaryAsBase64: deserialize bytes values as base64 strings instead of
- * Buffers. Defaults to false
- * - longsAsStrings: deserialize long values as strings instead of objects.
- * Defaults to true
- * - deprecatedArgumentOrder: Use the beta method argument order for client
- * methods, with optional arguments after the callback. Defaults to false.
- * This option is only a temporary stopgap measure to smooth an API breakage.
- * It is deprecated, and new code should not use it.
+ * Load a gRPC object from a .proto file.
+ * @memberof grpc
+ * @alias grpc.load
* @param {string|{root: string, file: string}} filename The file to load
* @param {string=} format The file format to expect. Must be either 'proto' or
* 'json'. Defaults to 'proto'
* @param {Object=} options Options to apply to the loaded file
+ * @param {bool=} [options.convertFieldsToCamelCase=false] Load this file with
+ * field names in camel case instead of their original case
+ * @param {bool=} [options.binaryAsBase64=false] deserialize bytes values as
+ * base64 strings instead of Buffers
+ * @param {bool=} [options.longsAsStrings=true] deserialize long values as
+ * strings instead of objects
+ * @param {bool=} [options.deprecatedArgumentOrder=false] use the beta method
+ * argument order for client methods, with optional arguments after the
+ * callback. This option is only a temporary stopgap measure to smooth an
+ * API breakage. It is deprecated, and new code should not use it.
* @return {Object<string, *>} The resulting gRPC object
*/
exports.load = function load(filename, format, options) {
@@ -168,6 +171,8 @@ var log_template = _.template(
* called. Note: the output format here is intended to be informational, and
* is not guaranteed to stay the same in the future.
* Logs will be directed to logger.error.
+ * @memberof grpc
+ * @alias grpc.setLogger
* @param {Console} logger A Console-like object.
*/
exports.setLogger = function setLogger(logger) {
@@ -187,6 +192,8 @@ exports.setLogger = function setLogger(logger) {
/**
* Sets the logger verbosity for gRPC module logging. The options are members
* of the grpc.logVerbosity map.
+ * @memberof grpc
+ * @alias grpc.setLogVerbosity
* @param {Number} verbosity The minimum severity to log
*/
exports.setLogVerbosity = function setLogVerbosity(verbosity) {
@@ -194,71 +201,70 @@ exports.setLogVerbosity = function setLogVerbosity(verbosity) {
grpc.setLogVerbosity(verbosity);
};
-/**
- * @see module:src/server.Server
- */
exports.Server = server.Server;
-/**
- * @see module:src/metadata
- */
exports.Metadata = Metadata;
-/**
- * Status name to code number mapping
- */
exports.status = constants.status;
-/**
- * Propagate flag name to number mapping
- */
exports.propagate = constants.propagate;
-/**
- * Call error name to code number mapping
- */
exports.callError = constants.callError;
-/**
- * Write flag name to code number mapping
- */
exports.writeFlags = constants.writeFlags;
-/**
- * Log verbosity setting name to code number mapping
- */
exports.logVerbosity = constants.logVerbosity;
-/**
- * Credentials factories
- */
exports.credentials = require('./src/credentials.js');
/**
* ServerCredentials factories
+ * @constructor ServerCredentials
+ * @memberof grpc
*/
exports.ServerCredentials = grpc.ServerCredentials;
/**
- * @see module:src/client.makeClientConstructor
+ * Create insecure server credentials
+ * @name grpc.ServerCredentials.createInsecure
+ * @kind function
+ * @return grpc.ServerCredentials
*/
-exports.makeGenericClientConstructor = client.makeClientConstructor;
/**
- * @see module:src/client.getClientChannel
+ * A private key and certificate pair
+ * @typedef {Object} grpc.ServerCredentials~keyCertPair
+ * @property {Buffer} privateKey The server's private key
+ * @property {Buffer} certChain The server's certificate chain
*/
-exports.getClientChannel = client.getClientChannel;
/**
- * @see module:src/client.waitForClientReady
+ * Create SSL server credentials
+ * @name grpc.ServerCredentials.createInsecure
+ * @kind function
+ * @param {?Buffer} rootCerts Root CA certificates for validating client
+ * certificates
+ * @param {Array<grpc.ServerCredentials~keyCertPair>} keyCertPairs A list of
+ * private key and certificate chain pairs to be used for authenticating
+ * the server
+ * @param {boolean} [checkClientCertificate=false] Indicates that the server
+ * should request and verify the client's certificates
+ * @return grpc.ServerCredentials
*/
+
+exports.makeGenericClientConstructor = client.makeClientConstructor;
+
+exports.getClientChannel = client.getClientChannel;
+
exports.waitForClientReady = client.waitForClientReady;
+/**
+ * @memberof grpc
+ * @alias grpc.closeClient
+ * @param {grpc.Client} client_obj The client to close
+ */
exports.closeClient = function closeClient(client_obj) {
client.Client.prototype.close.apply(client_obj);
};
-/**
- * @see module:src/client.Client
- */
exports.Client = client.Client;
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 16fe06a54d..cf4c104144 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@@ -43,8 +43,6 @@
* var Client = proto_obj.package.subpackage.ServiceName;
* var client = new Client(server_address, client_credentials);
* var call = client.unaryMethod(arguments, callback);
- *
- * @module
*/
'use strict';
@@ -70,13 +68,26 @@ var Duplex = stream.Duplex;
var util = require('util');
var version = require('../../../package.json').version;
+/**
+ * Initial response metadata sent by the server when it starts processing the
+ * call
+ * @event grpc~ClientUnaryCall#metadata
+ * @type {grpc.Metadata}
+ */
+
+/**
+ * Status of the call when it has completed.
+ * @event grpc~ClientUnaryCall#status
+ * @type grpc~StatusObject
+ */
+
util.inherits(ClientUnaryCall, EventEmitter);
/**
- * An EventEmitter. Used for unary calls
- * @constructor
+ * An EventEmitter. Used for unary calls.
+ * @constructor grpc~ClientUnaryCall
* @extends external:EventEmitter
- * @param {grpc.Call} call The call object associated with the request
+ * @param {grpc.internal~Call} call The call object associated with the request
*/
function ClientUnaryCall(call) {
EventEmitter.call(this);
@@ -88,14 +99,16 @@ util.inherits(ClientWritableStream, Writable);
/**
* A stream that the client can write to. Used for calls that are streaming from
* the client side.
- * @constructor
+ * @constructor grpc~ClientWritableStream
* @extends external:Writable
- * @borrows module:src/client~ClientUnaryCall#cancel as
- * module:src/client~ClientWritableStream#cancel
- * @borrows module:src/client~ClientUnaryCall#getPeer as
- * module:src/client~ClientWritableStream#getPeer
- * @param {grpc.Call} call The call object to send data with
- * @param {module:src/common~serialize=} [serialize=identity] Serialization
+ * @borrows grpc~ClientUnaryCall#cancel as grpc~ClientWritableStream#cancel
+ * @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientWritableStream#getPeer
+ * @borrows grpc~ClientUnaryCall#event:metadata as
+ * grpc~ClientWritableStream#metadata
+ * @borrows grpc~ClientUnaryCall#event:status as
+ * grpc~ClientWritableStream#status
+ * @param {grpc.internal~Call} call The call object to send data with
+ * @param {grpc~serialize=} [serialize=identity] Serialization
* function for writes.
*/
function ClientWritableStream(call, serialize) {
@@ -110,11 +123,24 @@ function ClientWritableStream(call, serialize) {
}
/**
+ * Write a message to the request stream. If serializing the argument fails,
+ * the call will be cancelled and the stream will end with an error.
+ * @name grpc~ClientWritableStream#write
+ * @kind function
+ * @override
+ * @param {*} message The message to write. Must be a valid argument to the
+ * serialize function of the corresponding method
+ * @param {grpc.writeFlags} flags Flags to modify how the message is written
+ * @param {Function} callback Callback for when this chunk of data is flushed
+ * @return {boolean} As defined for [Writable]{@link external:Writable}
+ */
+
+/**
* Attempt to write the given chunk. Calls the callback when done. This is an
* implementation of a method needed for implementing stream.Writable.
- * @access private
- * @param {Buffer} chunk The chunk to write
- * @param {string} encoding Used to pass write flags
+ * @private
+ * @param {*} chunk The chunk to write
+ * @param {grpc.writeFlags} encoding Used to pass write flags
* @param {function(Error=)} callback Called when the write is complete
*/
function _write(chunk, encoding, callback) {
@@ -155,14 +181,16 @@ util.inherits(ClientReadableStream, Readable);
/**
* A stream that the client can read from. Used for calls that are streaming
* from the server side.
- * @constructor
+ * @constructor grpc~ClientReadableStream
* @extends external:Readable
- * @borrows module:src/client~ClientUnaryCall#cancel as
- * module:src/client~ClientReadableStream#cancel
- * @borrows module:src/client~ClientUnaryCall#getPeer as
- * module:src/client~ClientReadableStream#getPeer
- * @param {grpc.Call} call The call object to read data with
- * @param {module:src/common~deserialize=} [deserialize=identity]
+ * @borrows grpc~ClientUnaryCall#cancel as grpc~ClientReadableStream#cancel
+ * @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientReadableStream#getPeer
+ * @borrows grpc~ClientUnaryCall#event:metadata as
+ * grpc~ClientReadableStream#metadata
+ * @borrows grpc~ClientUnaryCall#event:status as
+ * grpc~ClientReadableStream#status
+ * @param {grpc.internal~Call} call The call object to read data with
+ * @param {grpc~deserialize=} [deserialize=identity]
* Deserialization function for reads
*/
function ClientReadableStream(call, deserialize) {
@@ -183,7 +211,7 @@ function ClientReadableStream(call, deserialize) {
* parameter indicates that the call should end with that status. status
* defaults to OK if not provided.
* @param {Object!} status The status that the call should end with
- * @access private
+ * @private
*/
function _readsDone(status) {
/* jshint validthis: true */
@@ -202,7 +230,7 @@ ClientReadableStream.prototype._readsDone = _readsDone;
/**
* Called to indicate that we have received a status from the server.
- * @access private
+ * @private
*/
function _receiveStatus(status) {
/* jshint validthis: true */
@@ -215,7 +243,7 @@ ClientReadableStream.prototype._receiveStatus = _receiveStatus;
/**
* If we have both processed all incoming messages and received the status from
* the server, emit the status. Otherwise, do nothing.
- * @access private
+ * @private
*/
function _emitStatusIfDone() {
/* jshint validthis: true */
@@ -242,7 +270,7 @@ ClientReadableStream.prototype._emitStatusIfDone = _emitStatusIfDone;
/**
* Read the next object from the stream.
- * @access private
+ * @private
* @param {*} size Ignored because we use objectMode=true
*/
function _read(size) {
@@ -300,16 +328,19 @@ util.inherits(ClientDuplexStream, Duplex);
/**
* A stream that the client can read from or write to. Used for calls with
* duplex streaming.
- * @constructor
+ * @constructor grpc~ClientDuplexStream
* @extends external:Duplex
- * @borrows module:src/client~ClientUnaryCall#cancel as
- * module:src/client~ClientDuplexStream#cancel
- * @borrows module:src/client~ClientUnaryCall#getPeer as
- * module:src/client~ClientDuplexStream#getPeer
- * @param {grpc.Call} call Call object to proxy
- * @param {module:src/common~serialize=} [serialize=identity] Serialization
+ * @borrows grpc~ClientUnaryCall#cancel as grpc~ClientDuplexStream#cancel
+ * @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientDuplexStream#getPeer
+ * @borrows grpc~ClientWritableStream#write as grpc~ClientDuplexStream#write
+ * @borrows grpc~ClientUnaryCall#event:metadata as
+ * grpc~ClientDuplexStream#metadata
+ * @borrows grpc~ClientUnaryCall#event:status as
+ * grpc~ClientDuplexStream#status
+ * @param {grpc.internal~Call} call Call object to proxy
+ * @param {grpc~serialize=} [serialize=identity] Serialization
* function for requests
- * @param {module:src/common~deserialize=} [deserialize=identity]
+ * @param {grpc~deserialize=} [deserialize=identity]
* Deserialization function for responses
*/
function ClientDuplexStream(call, serialize, deserialize) {
@@ -336,8 +367,9 @@ ClientDuplexStream.prototype._read = _read;
ClientDuplexStream.prototype._write = _write;
/**
- * Cancel the ongoing call
- * @alias module:src/client~ClientUnaryCall#cancel
+ * Cancel the ongoing call. Results in the call ending with a CANCELLED status,
+ * unless it has already ended with some other status.
+ * @alias grpc~ClientUnaryCall#cancel
*/
function cancel() {
/* jshint validthis: true */
@@ -352,7 +384,7 @@ ClientDuplexStream.prototype.cancel = cancel;
/**
* Get the endpoint this call/stream is connected to.
* @return {string} The URI of the endpoint
- * @alias module:src/client~ClientUnaryCall#getPeer
+ * @alias grpc~ClientUnaryCall#getPeer
*/
function getPeer() {
/* jshint validthis: true */
@@ -368,33 +400,31 @@ ClientDuplexStream.prototype.getPeer = getPeer;
* Any client call type
* @typedef {(ClientUnaryCall|ClientReadableStream|
* ClientWritableStream|ClientDuplexStream)}
- * module:src/client~Call
+ * grpc.Client~Call
*/
/**
* Options that can be set on a call.
- * @typedef {Object} module:src/client~CallOptions
- * @property {(date|number)} deadline The deadline for the entire call to
- * complete. A value of Infinity indicates that no deadline should be set.
- * @property {(string)} host Server hostname to set on the call. Only meaningful
+ * @typedef {Object} grpc.Client~CallOptions
+ * @property {grpc~Deadline} deadline The deadline for the entire call to
+ * complete.
+ * @property {string} host Server hostname to set on the call. Only meaningful
* if different from the server address used to construct the client.
- * @property {module:src/client~Call} parent Parent call. Used in servers when
+ * @property {grpc.Client~Call} parent Parent call. Used in servers when
* making a call as part of the process of handling a call. Used to
* propagate some information automatically, as specified by
* propagate_flags.
* @property {number} propagate_flags Indicates which properties of a parent
* call should propagate to this call. Bitwise combination of flags in
- * [grpc.propagate]{@link module:index.propagate}.
- * @property {module:src/credentials~CallCredentials} credentials The
- * credentials that should be used to make this particular call.
+ * {@link grpc.propagate}.
+ * @property {grpc.credentials~CallCredentials} credentials The credentials that
+ * should be used to make this particular call.
*/
/**
- * Get a call object built with the provided options. Keys for options are
- * 'deadline', which takes a date or number, and 'host', which takes a string
- * and overrides the hostname to connect to.
+ * Get a call object built with the provided options.
* @access private
- * @param {module:src/client~CallOptions=} options Options object.
+ * @param {grpc.Client~CallOptions=} options Options object.
*/
function getCall(channel, method, options) {
var deadline;
@@ -422,14 +452,14 @@ function getCall(channel, method, options) {
/**
* A generic gRPC client. Primarily useful as a base class for generated clients
- * @alias module:src/client.Client
+ * @memberof grpc
* @constructor
* @param {string} address Server address to connect to
- * @param {module:src/credentials~ChannelCredentials} credentials Credentials to
- * use to connect to the server
+ * @param {grpc~ChannelCredentials} credentials Credentials to use to connect to
+ * the server
* @param {Object} options Options to apply to channel creation
*/
-var Client = exports.Client = function Client(address, credentials, options) {
+function Client(address, credentials, options) {
if (!options) {
options = {};
}
@@ -445,19 +475,13 @@ var Client = exports.Client = function Client(address, credentials, options) {
/* Private fields use $ as a prefix instead of _ because it is an invalid
* prefix of a method name */
this.$channel = new grpc.Channel(address, credentials, options);
-};
+}
-/**
- * @typedef {Error} module:src/client.Client~ServiceError
- * @property {number} code The error code, a key of
- * [grpc.status]{@link module:src/client.status}
- * @property {module:metadata.Metadata} metadata Metadata sent with the status
- * by the server, if any
- */
+exports.Client = Client;
/**
- * @callback module:src/client.Client~requestCallback
- * @param {?module:src/client.Client~ServiceError} error The error, if the call
+ * @callback grpc.Client~requestCallback
+ * @param {?grpc~ServiceError} error The error, if the call
* failed
* @param {*} value The response value, if the call succeeded
*/
@@ -466,17 +490,17 @@ var Client = exports.Client = function Client(address, credentials, options) {
* Make a unary request to the given method, using the given serialize
* and deserialize functions, with the given argument.
* @param {string} method The name of the method to request
- * @param {module:src/common~serialize} serialize The serialization function for
+ * @param {grpc~serialize} serialize The serialization function for
* inputs
- * @param {module:src/common~deserialize} deserialize The deserialization
+ * @param {grpc~deserialize} deserialize The deserialization
* function for outputs
* @param {*} argument The argument to the call. Should be serializable with
* serialize
- * @param {module:src/metadata.Metadata=} metadata Metadata to add to the call
- * @param {module:src/client~CallOptions=} options Options map
- * @param {module:src/client.Client~requestCallback} callback The callback to
+ * @param {grpc.Metadata=} metadata Metadata to add to the call
+ * @param {grpc.Client~CallOptions=} options Options map
+ * @param {grpc.Client~requestCallback} callback The callback to
* for when the response is received
- * @return {EventEmitter} An event emitter for stream related events
+ * @return {grpc~ClientUnaryCall} An event emitter for stream related events
*/
Client.prototype.makeUnaryRequest = function(method, serialize, deserialize,
argument, metadata, options,
@@ -548,17 +572,17 @@ Client.prototype.makeUnaryRequest = function(method, serialize, deserialize,
* Make a client stream request to the given method, using the given serialize
* and deserialize functions, with the given argument.
* @param {string} method The name of the method to request
- * @param {module:src/common~serialize} serialize The serialization function for
+ * @param {grpc~serialize} serialize The serialization function for
* inputs
- * @param {module:src/common~deserialize} deserialize The deserialization
+ * @param {grpc~deserialize} deserialize The deserialization
* function for outputs
- * @param {module:src/metadata.Metadata=} metadata Array of metadata key/value
- * pairs to add to the call
- * @param {module:src/client~CallOptions=} options Options map
- * @param {Client~requestCallback} callback The callback to for when the
+ * @param {grpc.Metadata=} metadata Array of metadata key/value pairs to add to
+ * the call
+ * @param {grpc.Client~CallOptions=} options Options map
+ * @param {grpc.Client~requestCallback} callback The callback to for when the
* response is received
- * @return {module:src/client~ClientWritableStream} An event emitter for stream
- * related events
+ * @return {grpc~ClientWritableStream} An event emitter for stream related
+ * events
*/
Client.prototype.makeClientStreamRequest = function(method, serialize,
deserialize, metadata,
@@ -631,17 +655,16 @@ Client.prototype.makeClientStreamRequest = function(method, serialize,
* Make a server stream request to the given method, with the given serialize
* and deserialize function, using the given argument
* @param {string} method The name of the method to request
- * @param {module:src/common~serialize} serialize The serialization function for
- * inputs
- * @param {module:src/common~deserialize} deserialize The deserialization
+ * @param {grpc~serialize} serialize The serialization function for inputs
+ * @param {grpc~deserialize} deserialize The deserialization
* function for outputs
* @param {*} argument The argument to the call. Should be serializable with
* serialize
- * @param {module:src/metadata.Metadata=} metadata Array of metadata key/value
- * pairs to add to the call
- * @param {module:src/client~CallOptions=} options Options map
- * @return {module:src/client~ClientReadableStream} An event emitter for stream
- * related events
+ * @param {grpc.Metadata=} metadata Array of metadata key/value pairs to add to
+ * the call
+ * @param {grpc.Client~CallOptions=} options Options map
+ * @return {grpc~ClientReadableStream} An event emitter for stream related
+ * events
*/
Client.prototype.makeServerStreamRequest = function(method, serialize,
deserialize, argument,
@@ -693,15 +716,13 @@ Client.prototype.makeServerStreamRequest = function(method, serialize,
/**
* Make a bidirectional stream request with this method on the given channel.
* @param {string} method The name of the method to request
- * @param {module:src/common~serialize} serialize The serialization function for
- * inputs
- * @param {module:src/common~deserialize} deserialize The deserialization
+ * @param {grpc~serialize} serialize The serialization function for inputs
+ * @param {grpc~deserialize} deserialize The deserialization
* function for outputs
- * @param {module:src/metadata.Metadata=} metadata Array of metadata key/value
+ * @param {grpc.Metadata=} metadata Array of metadata key/value
* pairs to add to the call
- * @param {module:src/client~CallOptions=} options Options map
- * @return {module:src/client~ClientDuplexStream} An event emitter for stream
- * related events
+ * @param {grpc.Client~CallOptions=} options Options map
+ * @return {grpc~ClientDuplexStream} An event emitter for stream related events
*/
Client.prototype.makeBidiStreamRequest = function(method, serialize,
deserialize, metadata,
@@ -743,6 +764,9 @@ Client.prototype.makeBidiStreamRequest = function(method, serialize,
return stream;
};
+/**
+ * Close this client.
+ */
Client.prototype.close = function() {
this.$channel.close();
};
@@ -761,8 +785,7 @@ Client.prototype.getChannel = function() {
* with an error if the attempt to connect to the server has unrecoverablly
* failed or if the deadline expires. This function will make the channel
* start connecting if it has not already done so.
- * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass
- * Infinity to wait forever.
+ * @param {grpc~Deadline} deadline When to stop waiting for a connection.
* @param {function(Error)} callback The callback to call when done attempting
* to connect.
*/
@@ -788,7 +811,7 @@ Client.prototype.waitForReady = function(deadline, callback) {
/**
* Map with short names for each of the requester maker functions. Used in
* makeClientConstructor
- * @access private
+ * @private
*/
var requester_funcs = {
unary: Client.prototype.makeUnaryRequest,
@@ -834,9 +857,15 @@ var deprecated_request_wrap = {
/**
* Creates a constructor for a client with the given methods, as specified in
- * the methods argument.
- * @param {module:src/common~ServiceDefinition} methods An object mapping
- * method names to method attributes
+ * the methods argument. The resulting class will have an instance method for
+ * each method in the service, which is a partial application of one of the
+ * [Client]{@link grpc.Client} request methods, depending on `requestSerialize`
+ * and `responseSerialize`, with the `method`, `serialize`, and `deserialize`
+ * arguments predefined.
+ * @memberof grpc
+ * @alias grpc~makeGenericClientConstructor
+ * @param {grpc~ServiceDefinition} methods An object mapping method names to
+ * method attributes
* @param {string} serviceName The fully qualified name of the service
* @param {Object} class_options An options object.
* @param {boolean=} [class_options.deprecatedArgumentOrder=false] Indicates
@@ -844,9 +873,8 @@ var deprecated_request_wrap = {
* arguments at the end instead of the callback at the end. This option
* is only a temporary stopgap measure to smooth an API breakage.
* It is deprecated, and new code should not use it.
- * @return {function(string, Object)} New client constructor, which is a
- * subclass of [grpc.Client]{@link module:src/client.Client}, and has the
- * same arguments as that constructor.
+ * @return {function} New client constructor, which is a subclass of
+ * {@link grpc.Client}, and has the same arguments as that constructor.
*/
exports.makeClientConstructor = function(methods, serviceName,
class_options) {
@@ -898,8 +926,11 @@ exports.makeClientConstructor = function(methods, serviceName,
/**
* Return the underlying channel object for the specified client
+ * @memberof grpc
+ * @alias grpc~getClientChannel
* @param {Client} client
* @return {Channel} The channel
+ * @see grpc.Client#getChannel
*/
exports.getClientChannel = function(client) {
return Client.prototype.getChannel.call(client);
@@ -911,22 +942,15 @@ exports.getClientChannel = function(client) {
* with an error if the attempt to connect to the server has unrecoverablly
* failed or if the deadline expires. This function will make the channel
* start connecting if it has not already done so.
+ * @memberof grpc
+ * @alias grpc~waitForClientReady
* @param {Client} client The client to wait on
- * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass
+ * @param {grpc~Deadline} deadline When to stop waiting for a connection. Pass
* Infinity to wait forever.
* @param {function(Error)} callback The callback to call when done attempting
* to connect.
+ * @see grpc.Client#waitForReady
*/
exports.waitForClientReady = function(client, deadline, callback) {
Client.prototype.waitForReady.call(client, deadline, callback);
};
-
-/**
- * Map of status code names to status codes
- */
-exports.status = constants.status;
-
-/**
- * See docs for client.callError
- */
-exports.callError = grpc.callError;
diff --git a/src/node/src/common.js b/src/node/src/common.js
index 4dad60e630..0f835317ea 100644
--- a/src/node/src/common.js
+++ b/src/node/src/common.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@@ -31,12 +31,6 @@
*
*/
-/**
- * This module contains functions that are common to client and server
- * code. None of them should be used directly by gRPC users.
- * @module
- */
-
'use strict';
var _ = require('lodash');
@@ -62,16 +56,19 @@ exports.wrapIgnoreNull = function wrapIgnoreNull(func) {
/**
* The logger object for the gRPC module. Defaults to console.
+ * @private
*/
exports.logger = console;
/**
* The current logging verbosity. 0 corresponds to logging everything
+ * @private
*/
exports.logVerbosity = 0;
/**
* Log a message if the severity is at least as high as the current verbosity
+ * @private
* @param {Number} severity A value of the grpc.logVerbosity map
* @param {String} message The message to log
*/
@@ -83,6 +80,7 @@ exports.log = function log(severity, message) {
/**
* Default options for loading proto files into gRPC
+ * @alias grpc~defaultLoadOptions
*/
exports.defaultGrpcOptions = {
convertFieldsToCamelCase: false,
@@ -95,6 +93,30 @@ exports.defaultGrpcOptions = {
// JSDoc definitions that are used in multiple other modules
/**
+ * Represents the status of a completed request. If `code` is
+ * {@link grpc.status}.OK, then the request has completed successfully.
+ * Otherwise, the request has failed, `details` will contain a description of
+ * the error. Either way, `metadata` contains the trailing response metadata
+ * sent by the server when it finishes processing the call.
+ * @typedef {object} grpc~StatusObject
+ * @property {number} code The error code, a key of {@link grpc.status}
+ * @property {string} details Human-readable description of the status
+ * @property {grpc.Metadata} metadata Trailing metadata sent with the status,
+ * if applicable
+ */
+
+/**
+ * Describes how a request has failed. The member `message` will be the same as
+ * `details` in {@link grpc~StatusObject}, and `code` and `metadata` are the
+ * same as in that object.
+ * @typedef {Error} grpc~ServiceError
+ * @property {number} code The error code, a key of {@link grpc.status} that is
+ * not `grpc.status.OK`
+ * @property {grpc.Metadata} metadata Trailing metadata sent with the status,
+ * if applicable
+ */
+
+/**
* The EventEmitter class in the event standard module
* @external EventEmitter
* @see https://nodejs.org/api/events.html#events_class_eventemitter
@@ -120,38 +142,46 @@ exports.defaultGrpcOptions = {
/**
* A serialization function
- * @callback module:src/common~serialize
+ * @callback grpc~serialize
* @param {*} value The value to serialize
* @return {Buffer} The value serialized as a byte sequence
*/
/**
* A deserialization function
- * @callback module:src/common~deserialize
+ * @callback grpc~deserialize
* @param {Buffer} data The byte sequence to deserialize
* @return {*} The data deserialized as a value
*/
/**
+ * The deadline of an operation. If it is a date, the deadline is reached at
+ * the date and time specified. If it is a finite number, it is treated as
+ * a number of milliseconds since the Unix Epoch. If it is Infinity, the
+ * deadline will never be reached. If it is -Infinity, the deadline has already
+ * passed.
+ * @typedef {(number|date)} grpc~Deadline
+ */
+
+/**
* An object that completely defines a service method signature.
- * @typedef {Object} module:src/common~MethodDefinition
+ * @typedef {Object} grpc~MethodDefinition
* @property {string} path The method's URL path
* @property {boolean} requestStream Indicates whether the method accepts
* a stream of requests
* @property {boolean} responseStream Indicates whether the method returns
* a stream of responses
- * @property {module:src/common~serialize} requestSerialize Serialization
+ * @property {grpc~serialize} requestSerialize Serialization
* function for request values
- * @property {module:src/common~serialize} responseSerialize Serialization
+ * @property {grpc~serialize} responseSerialize Serialization
* function for response values
- * @property {module:src/common~deserialize} requestDeserialize Deserialization
+ * @property {grpc~deserialize} requestDeserialize Deserialization
* function for request data
- * @property {module:src/common~deserialize} responseDeserialize Deserialization
+ * @property {grpc~deserialize} responseDeserialize Deserialization
* function for repsonse data
*/
/**
* An object that completely defines a service.
- * @typedef {Object.<string, module:src/common~MethodDefinition>}
- * module:src/common~ServiceDefinition
+ * @typedef {Object.<string, grpc~MethodDefinition>} grpc~ServiceDefinition
*/
diff --git a/src/node/src/constants.js b/src/node/src/constants.js
index 528dab120e..c441ee740b 100644
--- a/src/node/src/constants.js
+++ b/src/node/src/constants.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2017, Google Inc.
* All rights reserved.
*
@@ -31,16 +31,14 @@
*
*/
-/**
- * @module
- */
-
/* The comments about status codes are copied verbatim (with some formatting
* modifications) from include/grpc/impl/codegen/status.h, for the purpose of
* including them in generated documentation.
*/
/**
* Enum of status codes that gRPC can return
+ * @memberof grpc
+ * @alias grpc.status
* @readonly
* @enum {number}
*/
@@ -178,6 +176,8 @@ exports.status = {
* Users are encouraged to write propagation masks as deltas from the default.
* i.e. write `grpc.propagate.DEFAULTS & ~grpc.propagate.DEADLINE` to disable
* deadline propagation.
+ * @memberof grpc
+ * @alias grpc.propagate
* @enum {number}
*/
exports.propagate = {
@@ -194,9 +194,11 @@ exports.propagate = {
/**
* Call error constants. Call errors almost always indicate bugs in the gRPC
* library, and these error codes are mainly useful for finding those bugs.
+ * @memberof grpc
+ * @readonly
* @enum {number}
*/
-exports.callError = {
+const callError = {
OK: 0,
ERROR: 1,
NOT_ON_SERVER: 2,
@@ -213,9 +215,14 @@ exports.callError = {
PAYLOAD_TYPE_MISMATCH: 14
};
+exports.callError = callError;
+
/**
* Write flags: these can be bitwise or-ed to form write options that modify
* how data is written.
+ * @memberof grpc
+ * @alias grpc.writeFlags
+ * @readonly
* @enum {number}
*/
exports.writeFlags = {
@@ -232,6 +239,9 @@ exports.writeFlags = {
};
/**
+ * @memberof grpc
+ * @alias grpc.logVerbosity
+ * @readonly
* @enum {number}
*/
exports.logVerbosity = {
diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js
index b1e86bbd09..b1dbc1c450 100644
--- a/src/node/src/credentials.js
+++ b/src/node/src/credentials.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@@ -48,6 +48,7 @@
* For example, to create a client secured with SSL that uses Google
* default application credentials to authenticate:
*
+ * @example
* var channel_creds = credentials.createSsl(root_certs);
* (new GoogleAuth()).getApplicationDefault(function(err, credential) {
* var call_creds = credentials.createFromGoogleCredential(credential);
@@ -56,15 +57,25 @@
* var client = new Client(address, combined_creds);
* });
*
- * @module
+ * @namespace grpc.credentials
*/
'use strict';
var grpc = require('./grpc_extension');
+/**
+ * This cannot be constructed directly. Instead, instances of this class should
+ * be created using the factory functions in {@link grpc.credentials}
+ * @constructor grpc.credentials~CallCredentials
+ */
var CallCredentials = grpc.CallCredentials;
+/**
+ * This cannot be constructed directly. Instead, instances of this class should
+ * be created using the factory functions in {@link grpc.credentials}
+ * @constructor grpc.credentials~ChannelCredentials
+ */
var ChannelCredentials = grpc.ChannelCredentials;
var Metadata = require('./metadata.js');
@@ -76,24 +87,48 @@ var constants = require('./constants');
var _ = require('lodash');
/**
+ * @external GoogleCredential
+ * @see https://github.com/google/google-auth-library-nodejs
+ */
+
+/**
* Create an SSL Credentials object. If using a client-side certificate, both
* the second and third arguments must be passed.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createSsl
+ * @kind function
* @param {Buffer} root_certs The root certificate data
* @param {Buffer=} private_key The client certificate private key, if
* applicable
* @param {Buffer=} cert_chain The client certificate cert chain, if applicable
- * @return {ChannelCredentials} The SSL Credentials object
+ * @return {grpc.credentials.ChannelCredentials} The SSL Credentials object
*/
exports.createSsl = ChannelCredentials.createSsl;
/**
+ * @callback grpc.credentials~metadataCallback
+ * @param {Error} error The error, if getting metadata failed
+ * @param {grpc.Metadata} metadata The metadata
+ */
+
+/**
+ * @callback grpc.credentials~generateMetadata
+ * @param {Object} params Parameters that can modify metadata generation
+ * @param {string} params.service_url The URL of the service that the call is
+ * going to
+ * @param {grpc.credentials~metadataCallback} callback
+ */
+
+/**
* Create a gRPC credentials object from a metadata generation function. This
* function gets the service URL and a callback as parameters. The error
* passed to the callback can optionally have a 'code' value attached to it,
* which corresponds to a status code that this library uses.
- * @param {function(String, function(Error, Metadata))} metadata_generator The
- * function that generates metadata
- * @return {CallCredentials} The credentials object
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createFromMetadataGenerator
+ * @param {grpc.credentials~generateMetadata} metadata_generator The function
+ * that generates metadata
+ * @return {grpc.credentials.CallCredentials} The credentials object
*/
exports.createFromMetadataGenerator = function(metadata_generator) {
return CallCredentials.createFromPlugin(function(service_url, cb_data,
@@ -119,8 +154,11 @@ exports.createFromMetadataGenerator = function(metadata_generator) {
/**
* Create a gRPC credential from a Google credential object.
- * @param {Object} google_credential The Google credential object to use
- * @return {CallCredentials} The resulting credentials object
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createFromGoogleCredential
+ * @param {external:GoogleCredential} google_credential The Google credential
+ * object to use
+ * @return {grpc.credentials.CallCredentials} The resulting credentials object
*/
exports.createFromGoogleCredential = function(google_credential) {
return exports.createFromMetadataGenerator(function(auth_context, callback) {
@@ -141,6 +179,8 @@ exports.createFromGoogleCredential = function(google_credential) {
/**
* Combine a ChannelCredentials with any number of CallCredentials into a single
* ChannelCredentials object.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.combineChannelCredentials
* @param {ChannelCredentials} channel_credential The ChannelCredentials to
* start with
* @param {...CallCredentials} credentials The CallCredentials to compose
@@ -157,6 +197,8 @@ exports.combineChannelCredentials = function(channel_credential) {
/**
* Combine any number of CallCredentials into a single CallCredentials object
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.combineCallCredentials
* @param {...CallCredentials} credentials the CallCredentials to compose
* @return CallCredentials A credentials object that combines all of the input
* credentials
@@ -172,6 +214,9 @@ exports.combineCallCredentials = function() {
/**
* Create an insecure credentials object. This is used to create a channel that
* does not use SSL. This cannot be composed with anything.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createInsecure
+ * @kind function
* @return {ChannelCredentials} The insecure credentials object
*/
exports.createInsecure = ChannelCredentials.createInsecure;
diff --git a/src/node/src/grpc_extension.js b/src/node/src/grpc_extension.js
index 63a281ddbc..864da97314 100644
--- a/src/node/src/grpc_extension.js
+++ b/src/node/src/grpc_extension.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2016, Google Inc.
* All rights reserved.
*
diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js
index 92cf23998b..c757d520f8 100644
--- a/src/node/src/metadata.js
+++ b/src/node/src/metadata.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@@ -31,15 +31,6 @@
*
*/
-/**
- * Metadata module
- *
- * This module defines the Metadata class, which represents header and trailer
- * metadata for gRPC calls.
- *
- * @module
- */
-
'use strict';
var _ = require('lodash');
@@ -48,8 +39,8 @@ var grpc = require('./grpc_extension');
/**
* Class for storing metadata. Keys are normalized to lowercase ASCII.
+ * @memberof grpc
* @constructor
- * @alias module:src/metadata.Metadata
* @example
* var metadata = new metadata_module.Metadata();
* metadata.set('key1', 'value1');
diff --git a/src/node/src/protobuf_js_5_common.js b/src/node/src/protobuf_js_5_common.js
index 4041e05390..1663a3a400 100644
--- a/src/node/src/protobuf_js_5_common.js
+++ b/src/node/src/protobuf_js_5_common.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2017, Google Inc.
* All rights reserved.
*
@@ -31,6 +31,11 @@
*
*/
+/**
+ * @module
+ * @private
+ */
+
'use strict';
var _ = require('lodash');
diff --git a/src/node/src/protobuf_js_6_common.js b/src/node/src/protobuf_js_6_common.js
index 00f11f2736..91a458aa20 100644
--- a/src/node/src/protobuf_js_6_common.js
+++ b/src/node/src/protobuf_js_6_common.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2017, Google Inc.
* All rights reserved.
*
@@ -31,6 +31,11 @@
*
*/
+/**
+ * @module
+ * @private
+ */
+
'use strict';
var _ = require('lodash');
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 1d9cc7d2c1..ae4fcb1dc4 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -1,5 +1,5 @@
-/*
- *
+/**
+ * @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@@ -31,22 +31,6 @@
*
*/
-/**
- * Server module
- *
- * This module contains all the server code for Node gRPC: both the Server
- * class itself and the method handler code for all types of methods.
- *
- * For example, to create a Server, add a service, and start it:
- *
- * var server = new server_module.Server();
- * server.addProtoService(protobuf_service_descriptor, service_implementation);
- * server.bind('address:port', server_credential);
- * server.start();
- *
- * @module
- */
-
'use strict';
var _ = require('lodash');
@@ -70,9 +54,9 @@ var EventEmitter = require('events').EventEmitter;
/**
* Handle an error on a call by sending it as a status
- * @access private
- * @param {grpc.Call} call The call to send the error on
- * @param {Object} error The error object
+ * @private
+ * @param {grpc.internal~Call} call The call to send the error on
+ * @param {(Object|Error)} error The error object
*/
function handleError(call, error) {
var statusMetadata = new Metadata();
@@ -104,14 +88,14 @@ function handleError(call, error) {
/**
* Send a response to a unary or client streaming call.
- * @access private
+ * @private
* @param {grpc.Call} call The call to respond on
* @param {*} value The value to respond with
- * @param {function(*):Buffer=} serialize Serialization function for the
+ * @param {grpc~serialize} serialize Serialization function for the
* response
- * @param {Metadata=} metadata Optional trailing metadata to send with status
- * @param {number=} flags Flags for modifying how the message is sent.
- * Defaults to 0.
+ * @param {grpc.Metadata=} metadata Optional trailing metadata to send with
+ * status
+ * @param {number=} [flags=0] Flags for modifying how the message is sent.
*/
function sendUnaryResponse(call, value, serialize, metadata, flags) {
var end_batch = {};
@@ -146,7 +130,7 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) {
/**
* Initialize a writable stream. This is used for both the writable and duplex
* stream constructors.
- * @access private
+ * @private
* @param {Writable} stream The stream to set up
* @param {function(*):Buffer=} Serialization function for responses
*/
@@ -225,9 +209,9 @@ function setUpWritable(stream, serialize) {
/**
* Initialize a readable stream. This is used for both the readable and duplex
* stream constructors.
- * @access private
+ * @private
* @param {Readable} stream The stream to initialize
- * @param {function(Buffer):*=} deserialize Deserialization function for
+ * @param {grpc~deserialize} deserialize Deserialization function for
* incoming data.
*/
function setUpReadable(stream, deserialize) {
@@ -245,34 +229,88 @@ function setUpReadable(stream, deserialize) {
});
}
+/**
+ * Emitted when the call has been cancelled. After this has been emitted, the
+ * call's `cancelled` property will be set to `true`.
+ * @event grpc~ServerUnaryCall~cancelled
+ */
+
util.inherits(ServerUnaryCall, EventEmitter);
-function ServerUnaryCall(call) {
+/**
+ * An EventEmitter. Used for unary calls.
+ * @constructor grpc~ServerUnaryCall
+ * @extends external:EventEmitter
+ * @param {grpc.internal~Call} call The call object associated with the request
+ * @param {grpc.Metadata} metadata The request metadata from the client
+ */
+function ServerUnaryCall(call, metadata) {
EventEmitter.call(this);
this.call = call;
+ /**
+ * Indicates if the call has been cancelled
+ * @member {boolean} grpc~ServerUnaryCall#cancelled
+ */
+ this.cancelled = false;
+ /**
+ * The request metadata from the client
+ * @member {grpc.Metadata} grpc~ServerUnaryCall#metadata
+ */
+ this.metadata = metadata;
+ /**
+ * The request message from the client
+ * @member {*} grpc~ServerUnaryCall#request
+ */
+ this.request = undefined;
}
+/**
+ * Emitted when the call has been cancelled. After this has been emitted, the
+ * call's `cancelled` property will be set to `true`.
+ * @event grpc~ServerWritableStream~cancelled
+ */
+
util.inherits(ServerWritableStream, Writable);
/**
* A stream that the server can write to. Used for calls that are streaming from
* the server side.
- * @constructor
- * @param {grpc.Call} call The call object to send data with
- * @param {function(*):Buffer=} serialize Serialization function for writes
+ * @constructor grpc~ServerWritableStream
+ * @extends external:Writable
+ * @borrows grpc~ServerUnaryCall#sendMetadata as
+ * grpc~ServerWritableStream#sendMetadata
+ * @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerWritableStream#getPeer
+ * @param {grpc.internal~Call} call The call object to send data with
+ * @param {grpc.Metadata} metadata The request metadata from the client
+ * @param {grpc~serialize} serialize Serialization function for writes
*/
-function ServerWritableStream(call, serialize) {
+function ServerWritableStream(call, metadata, serialize) {
Writable.call(this, {objectMode: true});
this.call = call;
this.finished = false;
setUpWritable(this, serialize);
+ /**
+ * Indicates if the call has been cancelled
+ * @member {boolean} grpc~ServerWritableStream#cancelled
+ */
+ this.cancelled = false;
+ /**
+ * The request metadata from the client
+ * @member {grpc.Metadata} grpc~ServerWritableStream#metadata
+ */
+ this.metadata = metadata;
+ /**
+ * The request message from the client
+ * @member {*} grpc~ServerWritableStream#request
+ */
+ this.request = undefined;
}
/**
* Start writing a chunk of data. This is an implementation of a method required
* for implementing stream.Writable.
- * @access private
+ * @private
* @param {Buffer} chunk The chunk of data to write
* @param {string} encoding Used to pass write flags
* @param {function(Error=)} callback Callback to indicate that the write is
@@ -312,19 +350,40 @@ function _write(chunk, encoding, callback) {
ServerWritableStream.prototype._write = _write;
+/**
+ * Emitted when the call has been cancelled. After this has been emitted, the
+ * call's `cancelled` property will be set to `true`.
+ * @event grpc~ServerReadableStream~cancelled
+ */
+
util.inherits(ServerReadableStream, Readable);
/**
* A stream that the server can read from. Used for calls that are streaming
* from the client side.
- * @constructor
- * @param {grpc.Call} call The call object to read data with
- * @param {function(Buffer):*=} deserialize Deserialization function for reads
+ * @constructor grpc~ServerReadableStream
+ * @extends external:Readable
+ * @borrows grpc~ServerUnaryCall#sendMetadata as
+ * grpc~ServerReadableStream#sendMetadata
+ * @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerReadableStream#getPeer
+ * @param {grpc.internal~Call} call The call object to read data with
+ * @param {grpc.Metadata} metadata The request metadata from the client
+ * @param {grpc~deserialize} deserialize Deserialization function for reads
*/
-function ServerReadableStream(call, deserialize) {
+function ServerReadableStream(call, metadata, deserialize) {
Readable.call(this, {objectMode: true});
this.call = call;
setUpReadable(this, deserialize);
+ /**
+ * Indicates if the call has been cancelled
+ * @member {boolean} grpc~ServerReadableStream#cancelled
+ */
+ this.cancelled = false;
+ /**
+ * The request metadata from the client
+ * @member {grpc.Metadata} grpc~ServerReadableStream#metadata
+ */
+ this.metadata = metadata;
}
/**
@@ -381,22 +440,43 @@ function _read(size) {
ServerReadableStream.prototype._read = _read;
+/**
+ * Emitted when the call has been cancelled. After this has been emitted, the
+ * call's `cancelled` property will be set to `true`.
+ * @event grpc~ServerDuplexStream~cancelled
+ */
+
util.inherits(ServerDuplexStream, Duplex);
/**
* A stream that the server can read from or write to. Used for calls with
* duplex streaming.
- * @constructor
- * @param {grpc.Call} call Call object to proxy
- * @param {function(*):Buffer=} serialize Serialization function for requests
- * @param {function(Buffer):*=} deserialize Deserialization function for
+ * @constructor grpc~ServerDuplexStream
+ * @extends external:Duplex
+ * @borrows grpc~ServerUnaryCall#sendMetadata as
+ * grpc~ServerDuplexStream#sendMetadata
+ * @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerDuplexStream#getPeer
+ * @param {grpc.internal~Call} call Call object to proxy
+ * @param {grpc.Metadata} metadata The request metadata from the client
+ * @param {grpc~serialize} serialize Serialization function for requests
+ * @param {grpc~deserialize} deserialize Deserialization function for
* responses
*/
-function ServerDuplexStream(call, serialize, deserialize) {
+function ServerDuplexStream(call, metadata, serialize, deserialize) {
Duplex.call(this, {objectMode: true});
this.call = call;
setUpWritable(this, serialize);
setUpReadable(this, deserialize);
+ /**
+ * Indicates if the call has been cancelled
+ * @member {boolean} grpc~ServerReadableStream#cancelled
+ */
+ this.cancelled = false;
+ /**
+ * The request metadata from the client
+ * @member {grpc.Metadata} grpc~ServerReadableStream#metadata
+ */
+ this.metadata = metadata;
}
ServerDuplexStream.prototype._read = _read;
@@ -404,6 +484,7 @@ ServerDuplexStream.prototype._write = _write;
/**
* Send the initial metadata for a writable stream.
+ * @alias grpc~ServerUnaryCall#sendMetadata
* @param {Metadata} responseMetadata Metadata to send
*/
function sendMetadata(responseMetadata) {
@@ -430,6 +511,7 @@ ServerDuplexStream.prototype.sendMetadata = sendMetadata;
/**
* Get the endpoint this call/stream is connected to.
+ * @alias grpc~ServerUnaryCall#getPeer
* @return {string} The URI of the endpoint
*/
function getPeer() {
@@ -445,6 +527,7 @@ ServerDuplexStream.prototype.getPeer = getPeer;
/**
* Wait for the client to close, then emit a cancelled event if the client
* cancelled.
+ * @private
*/
function waitForCancel() {
/* jshint validthis: true */
@@ -468,18 +551,41 @@ ServerWritableStream.prototype.waitForCancel = waitForCancel;
ServerDuplexStream.prototype.waitForCancel = waitForCancel;
/**
+ * Callback function passed to server handlers that handle methods with unary
+ * responses.
+ * @callback grpc.Server~sendUnaryData
+ * @param {grpc~ServiceError} error An error, if the call failed
+ * @param {*} value The response value. Must be a valid argument to the
+ * `responseSerialize` method of the method that is being handled
+ * @param {grpc.Metadata=} trailer Trailing metadata to send, if applicable
+ * @param {grpc.writeFlags=} flags Flags to modify writing the response
+ */
+
+/**
+ * User-provided method to handle unary requests on a server
+ * @callback grpc.Server~handleUnaryCall
+ * @param {grpc~ServerUnaryCall} call The call object
+ * @param {grpc.Server~sendUnaryData} callback The callback to call to respond
+ * to the request
+ */
+
+/**
* Fully handle a unary call
- * @access private
- * @param {grpc.Call} call The call to handle
+ * @private
+ * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
- * @param {Metadata} metadata Metadata from the client
+ * @param {grpc~Server.handleUnaryCall} handler.func The handler function
+ * @param {grpc~deserialize} handler.deserialize The deserialization function
+ * for request data
+ * @param {grpc~serialize} handler.serialize The serialization function for
+ * response data
+ * @param {grpc.Metadata} metadata Metadata from the client
*/
function handleUnary(call, handler, metadata) {
- var emitter = new ServerUnaryCall(call);
+ var emitter = new ServerUnaryCall(call, metadata);
emitter.on('error', function(error) {
handleError(call, error);
});
- emitter.metadata = metadata;
emitter.waitForCancel();
var batch = {};
batch[grpc.opType.RECV_MESSAGE] = true;
@@ -512,16 +618,27 @@ function handleUnary(call, handler, metadata) {
}
/**
+ * User provided method to handle server streaming methods on the server.
+ * @callback grpc.Server~handleServerStreamingCall
+ * @param {grpc~ServerWritableStream} call The call object
+ */
+
+/**
* Fully handle a server streaming call
- * @access private
- * @param {grpc.Call} call The call to handle
+ * @private
+ * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
- * @param {Metadata} metadata Metadata from the client
+ * @param {grpc~Server.handleServerStreamingCall} handler.func The handler
+ * function
+ * @param {grpc~deserialize} handler.deserialize The deserialization function
+ * for request data
+ * @param {grpc~serialize} handler.serialize The serialization function for
+ * response data
+ * @param {grpc.Metadata} metadata Metadata from the client
*/
function handleServerStreaming(call, handler, metadata) {
- var stream = new ServerWritableStream(call, handler.serialize);
+ var stream = new ServerWritableStream(call, metadata, handler.serialize);
stream.waitForCancel();
- stream.metadata = metadata;
var batch = {};
batch[grpc.opType.RECV_MESSAGE] = true;
call.startBatch(batch, function(err, result) {
@@ -541,19 +658,32 @@ function handleServerStreaming(call, handler, metadata) {
}
/**
+ * User provided method to handle client streaming methods on the server.
+ * @callback grpc.Server~handleClientStreamingCall
+ * @param {grpc~ServerReadableStream} call The call object
+ * @param {grpc.Server~sendUnaryData} callback The callback to call to respond
+ * to the request
+ */
+
+/**
* Fully handle a client streaming call
* @access private
- * @param {grpc.Call} call The call to handle
+ * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
- * @param {Metadata} metadata Metadata from the client
+ * @param {grpc~Server.handleClientStreamingCall} handler.func The handler
+ * function
+ * @param {grpc~deserialize} handler.deserialize The deserialization function
+ * for request data
+ * @param {grpc~serialize} handler.serialize The serialization function for
+ * response data
+ * @param {grpc.Metadata} metadata Metadata from the client
*/
function handleClientStreaming(call, handler, metadata) {
- var stream = new ServerReadableStream(call, handler.deserialize);
+ var stream = new ServerReadableStream(call, metadata, handler.deserialize);
stream.on('error', function(error) {
handleError(call, error);
});
stream.waitForCancel();
- stream.metadata = metadata;
handler.func(stream, function(err, value, trailer, flags) {
stream.terminate();
if (err) {
@@ -568,17 +698,28 @@ function handleClientStreaming(call, handler, metadata) {
}
/**
+ * User provided method to handle bidirectional streaming calls on the server.
+ * @callback grpc.Server~handleBidiStreamingCall
+ * @param {grpc~ServerDuplexStream} call The call object
+ */
+
+/**
* Fully handle a bidirectional streaming call
- * @access private
- * @param {grpc.Call} call The call to handle
+ * @private
+ * @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
+ * @param {grpc~Server.handleBidiStreamingCall} handler.func The handler
+ * function
+ * @param {grpc~deserialize} handler.deserialize The deserialization function
+ * for request data
+ * @param {grpc~serialize} handler.serialize The serialization function for
+ * response data
* @param {Metadata} metadata Metadata from the client
*/
function handleBidiStreaming(call, handler, metadata) {
- var stream = new ServerDuplexStream(call, handler.serialize,
+ var stream = new ServerDuplexStream(call, metadata, handler.serialize,
handler.deserialize);
stream.waitForCancel();
- stream.metadata = metadata;
handler.func(stream);
}
@@ -592,96 +733,90 @@ var streamHandlers = {
/**
* Constructs a server object that stores request handlers and delegates
* incoming requests to those handlers
+ * @memberof grpc
* @constructor
* @param {Object=} options Options that should be passed to the internal server
* implementation
+ * @example
+ * var server = new grpc.Server();
+ * server.addProtoService(protobuf_service_descriptor, service_implementation);
+ * server.bind('address:port', server_credential);
+ * server.start();
*/
function Server(options) {
this.handlers = {};
- var handlers = this.handlers;
var server = new grpc.Server(options);
this._server = server;
this.started = false;
+}
+
+/**
+ * Start the server and begin handling requests
+ */
+Server.prototype.start = function() {
+ if (this.started) {
+ throw new Error('Server is already running');
+ }
+ var self = this;
+ this.started = true;
+ this._server.start();
/**
- * Start the server and begin handling requests
- * @this Server
+ * Handles the SERVER_RPC_NEW event. If there is a handler associated with
+ * the requested method, use that handler to respond to the request. Then
+ * wait for the next request
+ * @param {grpc.internal~Event} event The event to handle with tag
+ * SERVER_RPC_NEW
*/
- this.start = function() {
- if (this.started) {
- throw new Error('Server is already running');
+ function handleNewCall(err, event) {
+ if (err) {
+ return;
}
- this.started = true;
- server.start();
- /**
- * Handles the SERVER_RPC_NEW event. If there is a handler associated with
- * the requested method, use that handler to respond to the request. Then
- * wait for the next request
- * @param {grpc.Event} event The event to handle with tag SERVER_RPC_NEW
- */
- function handleNewCall(err, event) {
- if (err) {
- return;
- }
- var details = event.new_call;
- var call = details.call;
- var method = details.method;
- var metadata = Metadata._fromCoreRepresentation(details.metadata);
- if (method === null) {
- return;
- }
- server.requestCall(handleNewCall);
- var handler;
- if (handlers.hasOwnProperty(method)) {
- handler = handlers[method];
- } else {
- var batch = {};
- batch[grpc.opType.SEND_INITIAL_METADATA] =
- (new Metadata())._getCoreRepresentation();
- batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
- code: constants.status.UNIMPLEMENTED,
- details: '',
- metadata: {}
- };
- batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
- call.startBatch(batch, function() {});
- return;
- }
- streamHandlers[handler.type](call, handler, metadata);
+ var details = event.new_call;
+ var call = details.call;
+ var method = details.method;
+ var metadata = Metadata._fromCoreRepresentation(details.metadata);
+ if (method === null) {
+ return;
}
- server.requestCall(handleNewCall);
- };
-
- /**
- * Gracefully shuts down the server. The server will stop receiving new calls,
- * and any pending calls will complete. The callback will be called when all
- * pending calls have completed and the server is fully shut down. This method
- * is idempotent with itself and forceShutdown.
- * @param {function()} callback The shutdown complete callback
- */
- this.tryShutdown = function(callback) {
- server.tryShutdown(callback);
- };
+ self._server.requestCall(handleNewCall);
+ var handler;
+ if (self.handlers.hasOwnProperty(method)) {
+ handler = self.handlers[method];
+ } else {
+ var batch = {};
+ batch[grpc.opType.SEND_INITIAL_METADATA] =
+ (new Metadata())._getCoreRepresentation();
+ batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+ code: constants.status.UNIMPLEMENTED,
+ details: '',
+ metadata: {}
+ };
+ batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
+ call.startBatch(batch, function() {});
+ return;
+ }
+ streamHandlers[handler.type](call, handler, metadata);
+ }
+ this._server.requestCall(handleNewCall);
+};
- /**
- * Forcibly shuts down the server. The server will stop receiving new calls
- * and cancel all pending calls. When it returns, the server has shut down.
- * This method is idempotent with itself and tryShutdown, and it will trigger
- * any outstanding tryShutdown callbacks.
- */
- this.forceShutdown = function() {
- server.forceShutdown();
- };
-}
+/**
+ * Unified type for application handlers for all types of calls
+ * @typedef {(grpc.Server~handleUnaryCall
+ * |grpc.Server~handleClientStreamingCall
+ * |grpc.Server~handleServerStreamingCall
+ * |grpc.Server~handleBidiStreamingCall)} grpc.Server~handleCall
+ */
/**
* Registers a handler to handle the named method. Fails if there already is
* a handler for the given method. Returns true on success
* @param {string} name The name of the method that the provided function should
* handle/respond to.
- * @param {function} handler Function that takes a stream of request values and
- * returns a stream of response values
- * @param {function(*):Buffer} serialize Serialization function for responses
- * @param {function(Buffer):*} deserialize Deserialization function for requests
+ * @param {grpc.Server~handleCall} handler Function that takes a stream of
+ * request values and returns a stream of response values
+ * @param {grpc~serialize} serialize Serialization function for responses
+ * @param {grpc~deserialize} deserialize Deserialization function for requests
* @param {string} type The streaming type of method that this handles
* @return {boolean} True if the handler was set. False if a handler was already
* set for that name.
@@ -700,6 +835,27 @@ Server.prototype.register = function(name, handler, serialize, deserialize,
return true;
};
+/**
+ * Gracefully shuts down the server. The server will stop receiving new calls,
+ * and any pending calls will complete. The callback will be called when all
+ * pending calls have completed and the server is fully shut down. This method
+ * is idempotent with itself and forceShutdown.
+ * @param {function()} callback The shutdown complete callback
+ */
+Server.prototype.tryShutdown = function(callback) {
+ this._server.tryShutdown(callback);
+};
+
+/**
+ * Forcibly shuts down the server. The server will stop receiving new calls
+ * and cancel all pending calls. When it returns, the server has shut down.
+ * This method is idempotent with itself and tryShutdown, and it will trigger
+ * any outstanding tryShutdown callbacks.
+ */
+Server.prototype.forceShutdown = function() {
+ this._server.forceShutdown();
+};
+
var unimplementedStatusResponse = {
code: constants.status.UNIMPLEMENTED,
details: 'The server does not implement this method'
@@ -721,13 +877,10 @@ var defaultHandler = {
};
/**
- * Add a service to the server, with a corresponding implementation. If you are
- * generating this from a proto file, you should instead use
- * addProtoService.
- * @param {Object<String, *>} service The service descriptor, as
- * {@link module:src/common.getProtobufServiceAttrs} returns
- * @param {Object<String, function>} implementation Map of method names to
- * method implementation for the provided service.
+ * Add a service to the server, with a corresponding implementation.
+ * @param {grpc~ServiceDefinition} service The service descriptor
+ * @param {Object<String, grpc.Server~handleCall>} implementation Map of method
+ * names to method implementation for the provided service.
*/
Server.prototype.addService = function(service, implementation) {
if (!_.isObject(service) || !_.isObject(implementation)) {
@@ -788,10 +941,10 @@ var logAddProtoServiceDeprecationOnce = _.once(function() {
/**
* Add a proto service to the server, with a corresponding implementation
- * @deprecated Use grpc.load and Server#addService instead
+ * @deprecated Use {@link grpc.Server#addService} instead
* @param {Protobuf.Reflect.Service} service The proto service descriptor
- * @param {Object<String, function>} implementation Map of method names to
- * method implementation for the provided service.
+ * @param {Object<String, grpc.Server~handleCall>} implementation Map of method
+ * names to method implementation for the provided service.
*/
Server.prototype.addProtoService = function(service, implementation) {
var options;
@@ -815,10 +968,11 @@ Server.prototype.addProtoService = function(service, implementation) {
};
/**
- * Binds the server to the given port, with SSL enabled if creds is given
+ * Binds the server to the given port, with SSL disabled if creds is an
+ * insecure credentials object
* @param {string} port The port that the server should bind on, in the format
* "address:port"
- * @param {ServerCredentials=} creds Server credential object to be used for
+ * @param {grpc.ServerCredentials} creds Server credential object to be used for
* SSL. Pass an insecure credentials object for an insecure port.
*/
Server.prototype.bind = function(port, creds) {
@@ -828,7 +982,4 @@ Server.prototype.bind = function(port, creds) {
return this._server.addHttp2Port(port, creds);
};
-/**
- * @see module:src/server~Server
- */
exports.Server = Server;
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index d2f0511af2..6f1c269267 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -1322,14 +1322,14 @@ describe('Cancelling surface client', function() {
});
it('Should correctly cancel a unary call', function(done) {
var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) {
- assert.strictEqual(err.code, surface_client.status.CANCELLED);
+ assert.strictEqual(err.code, grpc.status.CANCELLED);
done();
});
call.cancel();
});
it('Should correctly cancel a client stream call', function(done) {
var call = client.sum(function(err, resp) {
- assert.strictEqual(err.code, surface_client.status.CANCELLED);
+ assert.strictEqual(err.code, grpc.status.CANCELLED);
done();
});
call.cancel();
@@ -1338,7 +1338,7 @@ describe('Cancelling surface client', function() {
var call = client.fib({'limit': 5});
call.on('data', function() {});
call.on('error', function(error) {
- assert.strictEqual(error.code, surface_client.status.CANCELLED);
+ assert.strictEqual(error.code, grpc.status.CANCELLED);
done();
});
call.cancel();
@@ -1347,7 +1347,7 @@ describe('Cancelling surface client', function() {
var call = client.divMany();
call.on('data', function() {});
call.on('error', function(error) {
- assert.strictEqual(error.code, surface_client.status.CANCELLED);
+ assert.strictEqual(error.code, grpc.status.CANCELLED);
done();
});
call.cancel();
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 9770301d09..5f8075467d 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -313,6 +313,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c',
+ 'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
diff --git a/test/core/census/intrusive_hash_map_test.c b/test/core/census/intrusive_hash_map_test.c
new file mode 100644
index 0000000000..a0a46ebadf
--- /dev/null
+++ b/test/core/census/intrusive_hash_map_test.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/core/ext/census/intrusive_hash_map.h"
+
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+#include "test/core/util/test_config.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* The initial size of an intrusive hash map will be 2 to this power. */
+static const uint32_t kInitialLog2Size = 4;
+
+/* Simple object used for testing intrusive_hash_map. */
+typedef struct object { uint64_t val; } object;
+
+/* Helper function to allocate and initialize object. */
+static inline object *make_new_object(uint64_t val) {
+ object *obj = (object *)gpr_malloc(sizeof(object));
+ obj->val = val;
+ return obj;
+}
+
+/* Wrapper struct for object. */
+typedef struct ptr_item {
+ INTRUSIVE_HASH_MAP_HEADER;
+ object *obj;
+} ptr_item;
+
+/* Helper function that creates a new hash map item. It is up to the user to
+ * free the item that was allocated. */
+static inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) {
+ ptr_item *new_item = (ptr_item *)gpr_malloc(sizeof(ptr_item));
+ new_item->IHM_key = key;
+ new_item->IHM_hash_link = NULL;
+ new_item->obj = make_new_object(value);
+ return new_item;
+}
+
+/* Helper function to deallocate ptr_item. */
+static void free_ptr_item(void *ptr) { gpr_free(((ptr_item *)ptr)->obj); }
+
+/* Simple string object used for testing intrusive_hash_map. */
+typedef struct string_item {
+ INTRUSIVE_HASH_MAP_HEADER;
+ // User data.
+ char buf[32];
+ uint16_t len;
+} string_item;
+
+/* Helper function to allocate and initialize string object. */
+static string_item *make_string_item(uint64_t key, const char *buf,
+ uint16_t len) {
+ string_item *item = (string_item *)gpr_malloc(sizeof(string_item));
+ item->IHM_key = key;
+ item->IHM_hash_link = NULL;
+ item->len = len;
+ memcpy(item->buf, buf, sizeof(char) * len);
+ return item;
+}
+
+/* Helper function for comparing two string objects. */
+static bool compare_string_item(const string_item *A, const string_item *B) {
+ if (A->IHM_key != B->IHM_key || A->len != B->len)
+ return false;
+ else {
+ for (int i = 0; i < A->len; ++i) {
+ if (A->buf[i] != B->buf[i]) return false;
+ }
+ }
+
+ return true;
+}
+
+void test_empty() {
+ intrusive_hash_map hash_map;
+ intrusive_hash_map_init(&hash_map, kInitialLog2Size);
+ GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map));
+ GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
+ intrusive_hash_map_free(&hash_map, NULL);
+}
+
+void test_single_item() {
+ intrusive_hash_map hash_map;
+ intrusive_hash_map_init(&hash_map, kInitialLog2Size);
+
+ ptr_item *new_item = make_ptr_item(10, 20);
+ bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item);
+ GPR_ASSERT(ok);
+
+ ptr_item *item1 =
+ (ptr_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10);
+ GPR_ASSERT(item1->obj->val == 20);
+ GPR_ASSERT(item1 == new_item);
+
+ ptr_item *item2 =
+ (ptr_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10);
+ GPR_ASSERT(item2 == new_item);
+
+ gpr_free(new_item->obj);
+ gpr_free(new_item);
+ GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map));
+ intrusive_hash_map_free(&hash_map, &free_ptr_item);
+}
+
+void test_two_items() {
+ intrusive_hash_map hash_map;
+ intrusive_hash_map_init(&hash_map, kInitialLog2Size);
+
+ string_item *new_item1 = make_string_item(10, "test1", 5);
+ bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1);
+ GPR_ASSERT(ok);
+ string_item *new_item2 = make_string_item(20, "test2", 5);
+ ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item2);
+ GPR_ASSERT(ok);
+
+ string_item *item1 =
+ (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)10);
+ GPR_ASSERT(compare_string_item(new_item1, item1));
+ GPR_ASSERT(item1 == new_item1);
+ string_item *item2 =
+ (string_item *)intrusive_hash_map_find(&hash_map, (uint64_t)20);
+ GPR_ASSERT(compare_string_item(new_item2, item2));
+ GPR_ASSERT(item2 == new_item2);
+
+ item1 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)10);
+ GPR_ASSERT(item1 == new_item1);
+ item2 = (string_item *)intrusive_hash_map_erase(&hash_map, (uint64_t)20);
+ GPR_ASSERT(item2 == new_item2);
+
+ gpr_free(new_item1);
+ gpr_free(new_item2);
+ GPR_ASSERT(0 == intrusive_hash_map_size(&hash_map));
+ intrusive_hash_map_free(&hash_map, NULL);
+}
+
+// Test resetting and clearing the hash map.
+void test_reset_clear() {
+ intrusive_hash_map hash_map;
+ intrusive_hash_map_init(&hash_map, kInitialLog2Size);
+
+ // Add some data to the hash_map.
+ for (uint64_t i = 0; i < 3; ++i) {
+ intrusive_hash_map_insert(&hash_map, (hm_item *)make_ptr_item(i, i));
+ }
+ GPR_ASSERT(3 == intrusive_hash_map_size(&hash_map));
+
+ // Test find.
+ for (uint64_t i = 0; i < 3; ++i) {
+ ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i);
+ GPR_ASSERT(item != NULL);
+ GPR_ASSERT(item->IHM_key == i && item->obj->val == i);
+ }
+
+ intrusive_hash_map_clear(&hash_map, &free_ptr_item);
+ GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
+ intrusive_hash_map_free(&hash_map, &free_ptr_item);
+}
+
+// Check that the hash_map contains every key between [min_value, max_value]
+// (inclusive).
+void check_hash_map_values(intrusive_hash_map *hash_map, uint64_t min_value,
+ uint64_t max_value) {
+ GPR_ASSERT(intrusive_hash_map_size(hash_map) == max_value - min_value + 1);
+
+ for (uint64_t i = min_value; i <= max_value; ++i) {
+ ptr_item *item = (ptr_item *)intrusive_hash_map_find(hash_map, i);
+ GPR_ASSERT(item != NULL);
+ GPR_ASSERT(item->obj->val == i);
+ }
+}
+
+// Add many items and cause the hash_map to extend.
+void test_extend() {
+ intrusive_hash_map hash_map;
+ intrusive_hash_map_init(&hash_map, kInitialLog2Size);
+
+ const uint64_t kNumValues = (1 << 16);
+
+ for (uint64_t i = 0; i < kNumValues; ++i) {
+ ptr_item *item = make_ptr_item(i, i);
+ bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item);
+ GPR_ASSERT(ok);
+ if (i % 1000 == 0) {
+ check_hash_map_values(&hash_map, 0, i);
+ }
+ }
+
+ for (uint64_t i = 0; i < kNumValues; ++i) {
+ ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, i);
+ GPR_ASSERT(item != NULL);
+ GPR_ASSERT(item->IHM_key == i && item->obj->val == i);
+ ptr_item *item2 = (ptr_item *)intrusive_hash_map_erase(&hash_map, i);
+ GPR_ASSERT(item == item2);
+ gpr_free(item->obj);
+ gpr_free(item);
+ }
+
+ GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
+ intrusive_hash_map_free(&hash_map, &free_ptr_item);
+}
+
+void test_stress() {
+ intrusive_hash_map hash_map;
+ intrusive_hash_map_init(&hash_map, kInitialLog2Size);
+ size_t n = 0;
+
+ // Randomly add and insert entries 1000000 times.
+ for (uint64_t i = 0; i < 1000000; ++i) {
+ int op = rand() & 0x1;
+
+ switch (op) {
+ // Case 0 is insertion of entry.
+ case 0: {
+ uint64_t key = (uint64_t)(rand() % 10000);
+ ptr_item *item = make_ptr_item(key, key);
+ bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)item);
+ if (ok) {
+ n++;
+ } else {
+ gpr_free(item->obj);
+ gpr_free(item);
+ }
+ break;
+ }
+ // Case 1 is removal of entry.
+ case 1: {
+ uint64_t key = (uint64_t)(rand() % 10000);
+ ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, key);
+ if (item != NULL) {
+ n--;
+ GPR_ASSERT(key == item->obj->val);
+ ptr_item *item2 =
+ (ptr_item *)intrusive_hash_map_erase(&hash_map, key);
+ GPR_ASSERT(item == item2);
+ gpr_free(item->obj);
+ gpr_free(item);
+ }
+ break;
+ }
+ }
+ }
+ // Check size
+ GPR_ASSERT(n == intrusive_hash_map_size(&hash_map));
+
+ // Clean the hash_map up.
+ intrusive_hash_map_clear(&hash_map, &free_ptr_item);
+ GPR_ASSERT(intrusive_hash_map_empty(&hash_map));
+ intrusive_hash_map_free(&hash_map, &free_ptr_item);
+}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+ gpr_time_init();
+ srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
+
+ test_empty();
+ test_single_item();
+ test_two_items();
+ test_reset_clear();
+ test_extend();
+ test_stress();
+
+ return 0;
+}
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index eb0883b797..15410dec01 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -883,6 +883,9 @@ src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_filter.h \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
+src/core/ext/census/intrusive_hash_map.c \
+src/core/ext/census/intrusive_hash_map.h \
+src/core/ext/census/intrusive_hash_map_internal.h \
src/core/ext/census/mlog.c \
src/core/ext/census/mlog.h \
src/core/ext/census/operation.c \
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index ec2836ec42..97e079d8a8 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -191,6 +191,23 @@
"headers": [],
"is_filegroup": false,
"language": "c",
+ "name": "census_intrusive_hash_map_test",
+ "src": [
+ "test/core/census/intrusive_hash_map_test.c"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c",
"name": "census_resource_test",
"src": [
"test/core/census/resource_test.c"
@@ -7541,6 +7558,8 @@
"src/core/ext/census/gen/census.pb.h",
"src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h",
+ "src/core/ext/census/intrusive_hash_map.h",
+ "src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
@@ -7571,6 +7590,9 @@
"src/core/ext/census/grpc_filter.h",
"src/core/ext/census/grpc_plugin.c",
"src/core/ext/census/initialize.c",
+ "src/core/ext/census/intrusive_hash_map.c",
+ "src/core/ext/census/intrusive_hash_map.h",
+ "src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.c",
"src/core/ext/census/mlog.h",
"src/core/ext/census/operation.c",
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index d1e3a99a08..82db441a1a 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -237,6 +237,28 @@
"flaky": false,
"gtest": false,
"language": "c",
+ "name": "census_intrusive_hash_map_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ]
+ },
+ {
+ "args": [],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": false,
+ "language": "c",
"name": "census_resource_test",
"platforms": [
"linux",
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 97a75e7762..284dd68c16 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -129,6 +129,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_context_test", "vcxp
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_intrusive_hash_map_test", "vcxproj\test\census_intrusive_hash_map_test\census_intrusive_hash_map_test.vcxproj", "{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}"
+ ProjectSection(myProperties) = preProject
+ lib = "False"
+ EndProjectSection
+ ProjectSection(ProjectDependencies) = postProject
+ {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+ {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+ {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+ {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+ EndProjectSection
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_resource_test", "vcxproj\test\census_resource_test\census_resource_test.vcxproj", "{18CF99B5-3C61-EC3D-9509-3C95334C3B88}"
ProjectSection(myProperties) = preProject
lib = "False"
@@ -1899,6 +1910,22 @@ Global
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|Win32.Build.0 = Release|Win32
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.ActiveCfg = Release|x64
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.Build.0 = Release|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|x64.ActiveCfg = Debug|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|Win32.ActiveCfg = Release|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|x64.ActiveCfg = Release|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|Win32.Build.0 = Debug|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug|x64.Build.0 = Debug|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|Win32.Build.0 = Release|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release|x64.Build.0 = Release|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|Win32.Build.0 = Debug|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|x64.ActiveCfg = Debug|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Debug-DLL|x64.Build.0 = Debug|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|Win32.ActiveCfg = Release|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|Win32.Build.0 = Release|Win32
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|x64.ActiveCfg = Release|x64
+ {BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}.Release-DLL|x64.Build.0 = Release|x64
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|Win32.ActiveCfg = Debug|Win32
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|x64.ActiveCfg = Debug|x64
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 2ccda23694..1303366574 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -504,6 +504,8 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
@@ -993,6 +995,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 3a1c1f9c5a..9f25a1c179 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -712,6 +712,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
+ <Filter>src\core\ext\census</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
@@ -1454,6 +1457,12 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h">
+ <Filter>src\core\ext\census</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h">
+ <Filter>src\core\ext\census</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index d084d70702..ac403a7c48 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -469,6 +469,8 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
@@ -900,6 +902,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\operation.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index ba826852a3..9fee2ec22b 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -625,6 +625,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\initialize.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.c">
+ <Filter>src\core\ext\census</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\mlog.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
@@ -1289,6 +1292,12 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h">
+ <Filter>src\core\ext\census</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h">
+ <Filter>src\core\ext\census</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj b/vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj
new file mode 100644
index 0000000000..46ea06b2a0
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BD364959-BDBF-ABD2-C6D1-FC838EBEBB60}</ProjectGuid>
+ <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+ <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+ <TargetName>census_intrusive_hash_map_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'">
+ <TargetName>census_intrusive_hash_map_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\test\core\census\intrusive_hash_map_test.c">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+ <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+ <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+ <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+ <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ </ImportGroup>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+ </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj.filters b/vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj.filters
new file mode 100644
index 0000000000..2dfa300e97
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_intrusive_hash_map_test/census_intrusive_hash_map_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\test\core\census\intrusive_hash_map_test.c">
+ <Filter>test\core\census</Filter>
+ </ClCompile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="test">
+ <UniqueIdentifier>{24bfacc6-bd89-4cdf-4183-3ff53180fa48}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core">
+ <UniqueIdentifier>{71b1debf-71c7-c1e9-9e01-21330ede0d7f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core\census">
+ <UniqueIdentifier>{0228063a-a601-967e-27ed-9f6197cb3629}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+