diff options
25 files changed, 1205 insertions, 0 deletions
@@ -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 ) @@ -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 @@ -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/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> + |