diff --git a/BUILD b/BUILD
index 58043459000..94f2e2a1b75 100644
--- a/BUILD
+++ b/BUILD
@@ -575,6 +575,7 @@ grpc_cc_library(
"src/core/lib/gpr/wrap_memcpy.cc",
"src/core/lib/gprpp/arena.cc",
"src/core/lib/gprpp/fork.cc",
+ "src/core/lib/gprpp/global_config_env.cc",
"src/core/lib/gprpp/thd_posix.cc",
"src/core/lib/gprpp/thd_windows.cc",
"src/core/lib/profiling/basic_timers.cc",
@@ -601,6 +602,10 @@ grpc_cc_library(
"src/core/lib/gprpp/arena.h",
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/fork.h",
+ "src/core/lib/gprpp/global_config_custom.h",
+ "src/core/lib/gprpp/global_config_env.h",
+ "src/core/lib/gprpp/global_config_generic.h",
+ "src/core/lib/gprpp/global_config.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/map.h",
"src/core/lib/gprpp/memory.h",
diff --git a/BUILD.gn b/BUILD.gn
index 38b2f0e6502..f642f6af1c2 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -184,6 +184,11 @@ config("grpc_config") {
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/fork.cc",
"src/core/lib/gprpp/fork.h",
+ "src/core/lib/gprpp/global_config.h",
+ "src/core/lib/gprpp/global_config_custom.h",
+ "src/core/lib/gprpp/global_config_env.cc",
+ "src/core/lib/gprpp/global_config_env.h",
+ "src/core/lib/gprpp/global_config_generic.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/map.h",
"src/core/lib/gprpp/memory.h",
@@ -1170,6 +1175,10 @@ config("grpc_config") {
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/debug_location.h",
"src/core/lib/gprpp/fork.h",
+ "src/core/lib/gprpp/global_config.h",
+ "src/core/lib/gprpp/global_config_custom.h",
+ "src/core/lib/gprpp/global_config_env.h",
+ "src/core/lib/gprpp/global_config_generic.h",
"src/core/lib/gprpp/inlined_vector.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/map.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b93ab08af4..da2326525da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -629,6 +629,8 @@ add_dependencies(buildtests_cxx error_details_test)
add_dependencies(buildtests_cxx exception_test)
add_dependencies(buildtests_cxx filter_end2end_test)
add_dependencies(buildtests_cxx generic_end2end_test)
+add_dependencies(buildtests_cxx global_config_env_test)
+add_dependencies(buildtests_cxx global_config_test)
add_dependencies(buildtests_cxx golden_file_test)
add_dependencies(buildtests_cxx grpc_alts_credentials_options_test)
add_dependencies(buildtests_cxx grpc_cli)
@@ -873,6 +875,7 @@ add_library(gpr
src/core/lib/gpr/wrap_memcpy.cc
src/core/lib/gprpp/arena.cc
src/core/lib/gprpp/fork.cc
+ src/core/lib/gprpp/global_config_env.cc
src/core/lib/gprpp/thd_posix.cc
src/core/lib/gprpp/thd_windows.cc
src/core/lib/profiling/basic_timers.cc
@@ -13422,6 +13425,80 @@ target_link_libraries(generic_end2end_test
)
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
+add_executable(global_config_env_test
+ test/core/gprpp/global_config_env_test.cc
+ third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(global_config_env_test
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+ PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+ PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+ PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+ PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+ PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+ PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+ PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
+ PRIVATE third_party/googletest/googletest/include
+ PRIVATE third_party/googletest/googletest
+ PRIVATE third_party/googletest/googlemock/include
+ PRIVATE third_party/googletest/googlemock
+ PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(global_config_env_test
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ gpr
+ grpc_test_util_unsecure
+ ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
+add_executable(global_config_test
+ test/core/gprpp/global_config_test.cc
+ third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(global_config_test
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+ PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+ PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+ PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+ PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+ PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+ PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+ PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
+ PRIVATE third_party/googletest/googletest/include
+ PRIVATE third_party/googletest/googletest
+ PRIVATE third_party/googletest/googlemock/include
+ PRIVATE third_party/googletest/googlemock
+ PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(global_config_test
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ gpr
+ grpc_test_util_unsecure
+ ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
diff --git a/Makefile b/Makefile
index 700e789265e..2cf316590ec 100644
--- a/Makefile
+++ b/Makefile
@@ -1206,6 +1206,8 @@ error_details_test: $(BINDIR)/$(CONFIG)/error_details_test
exception_test: $(BINDIR)/$(CONFIG)/exception_test
filter_end2end_test: $(BINDIR)/$(CONFIG)/filter_end2end_test
generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test
+global_config_env_test: $(BINDIR)/$(CONFIG)/global_config_env_test
+global_config_test: $(BINDIR)/$(CONFIG)/global_config_test
golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test
grpc_alts_credentials_options_test: $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test
grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli
@@ -1682,6 +1684,8 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/exception_test \
$(BINDIR)/$(CONFIG)/filter_end2end_test \
$(BINDIR)/$(CONFIG)/generic_end2end_test \
+ $(BINDIR)/$(CONFIG)/global_config_env_test \
+ $(BINDIR)/$(CONFIG)/global_config_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
@@ -1826,6 +1830,8 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/exception_test \
$(BINDIR)/$(CONFIG)/filter_end2end_test \
$(BINDIR)/$(CONFIG)/generic_end2end_test \
+ $(BINDIR)/$(CONFIG)/global_config_env_test \
+ $(BINDIR)/$(CONFIG)/global_config_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
@@ -2318,6 +2324,10 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/filter_end2end_test || ( echo test filter_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing generic_end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 )
+ $(E) "[RUN] Testing global_config_env_test"
+ $(Q) $(BINDIR)/$(CONFIG)/global_config_env_test || ( echo test global_config_env_test failed ; exit 1 )
+ $(E) "[RUN] Testing global_config_test"
+ $(Q) $(BINDIR)/$(CONFIG)/global_config_test || ( echo test global_config_test failed ; exit 1 )
$(E) "[RUN] Testing golden_file_test"
$(Q) $(BINDIR)/$(CONFIG)/golden_file_test || ( echo test golden_file_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_alts_credentials_options_test"
@@ -3354,6 +3364,7 @@ LIBGPR_SRC = \
src/core/lib/gpr/wrap_memcpy.cc \
src/core/lib/gprpp/arena.cc \
src/core/lib/gprpp/fork.cc \
+ src/core/lib/gprpp/global_config_env.cc \
src/core/lib/gprpp/thd_posix.cc \
src/core/lib/gprpp/thd_windows.cc \
src/core/lib/profiling/basic_timers.cc \
@@ -16390,6 +16401,92 @@ endif
endif
+GLOBAL_CONFIG_ENV_TEST_SRC = \
+ test/core/gprpp/global_config_env_test.cc \
+
+GLOBAL_CONFIG_ENV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GLOBAL_CONFIG_ENV_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/global_config_env_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/global_config_env_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/global_config_env_test: $(PROTOBUF_DEP) $(GLOBAL_CONFIG_ENV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(GLOBAL_CONFIG_ENV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/global_config_env_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/gprpp/global_config_env_test.o: $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a
+
+deps_global_config_env_test: $(GLOBAL_CONFIG_ENV_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GLOBAL_CONFIG_ENV_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+GLOBAL_CONFIG_TEST_SRC = \
+ test/core/gprpp/global_config_test.cc \
+
+GLOBAL_CONFIG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GLOBAL_CONFIG_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/global_config_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/global_config_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/global_config_test: $(PROTOBUF_DEP) $(GLOBAL_CONFIG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(GLOBAL_CONFIG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/global_config_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/gprpp/global_config_test.o: $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a
+
+deps_global_config_test: $(GLOBAL_CONFIG_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GLOBAL_CONFIG_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
GOLDEN_FILE_TEST_SRC = \
$(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc \
test/cpp/codegen/golden_file_test.cc \
diff --git a/build.yaml b/build.yaml
index 848bf4ba072..f333d982961 100644
--- a/build.yaml
+++ b/build.yaml
@@ -148,6 +148,7 @@ filegroups:
- src/core/lib/gpr/wrap_memcpy.cc
- src/core/lib/gprpp/arena.cc
- src/core/lib/gprpp/fork.cc
+ - src/core/lib/gprpp/global_config_env.cc
- src/core/lib/gprpp/thd_posix.cc
- src/core/lib/gprpp/thd_windows.cc
- src/core/lib/profiling/basic_timers.cc
@@ -194,6 +195,10 @@ filegroups:
- src/core/lib/gprpp/arena.h
- src/core/lib/gprpp/atomic.h
- src/core/lib/gprpp/fork.h
+ - src/core/lib/gprpp/global_config.h
+ - src/core/lib/gprpp/global_config_custom.h
+ - src/core/lib/gprpp/global_config_env.h
+ - src/core/lib/gprpp/global_config_generic.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/map.h
- src/core/lib/gprpp/memory.h
@@ -4722,6 +4727,24 @@ targets:
- grpc++
- grpc
- gpr
+- name: global_config_env_test
+ build: test
+ language: c++
+ src:
+ - test/core/gprpp/global_config_env_test.cc
+ deps:
+ - gpr
+ - grpc_test_util_unsecure
+ uses_polling: false
+- name: global_config_test
+ build: test
+ language: c++
+ src:
+ - test/core/gprpp/global_config_test.cc
+ deps:
+ - gpr
+ - grpc_test_util_unsecure
+ uses_polling: false
- name: golden_file_test
gtest: true
build: test
diff --git a/config.m4 b/config.m4
index 205d425868e..4616922a38b 100644
--- a/config.m4
+++ b/config.m4
@@ -79,6 +79,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/gpr/wrap_memcpy.cc \
src/core/lib/gprpp/arena.cc \
src/core/lib/gprpp/fork.cc \
+ src/core/lib/gprpp/global_config_env.cc \
src/core/lib/gprpp/thd_posix.cc \
src/core/lib/gprpp/thd_windows.cc \
src/core/lib/profiling/basic_timers.cc \
diff --git a/config.w32 b/config.w32
index 3b0fcdd202e..63048c73492 100644
--- a/config.w32
+++ b/config.w32
@@ -54,6 +54,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\gpr\\wrap_memcpy.cc " +
"src\\core\\lib\\gprpp\\arena.cc " +
"src\\core\\lib\\gprpp\\fork.cc " +
+ "src\\core\\lib\\gprpp\\global_config_env.cc " +
"src\\core\\lib\\gprpp\\thd_posix.cc " +
"src\\core\\lib\\gprpp\\thd_windows.cc " +
"src\\core\\lib\\profiling\\basic_timers.cc " +
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index 3ecdcfe82a4..1809171006f 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -267,6 +267,10 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/fork.h',
+ 'src/core/lib/gprpp/global_config.h',
+ 'src/core/lib/gprpp/global_config_custom.h',
+ 'src/core/lib/gprpp/global_config_env.h',
+ 'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
@@ -589,6 +593,10 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/fork.h',
+ 'src/core/lib/gprpp/global_config.h',
+ 'src/core/lib/gprpp/global_config_custom.h',
+ 'src/core/lib/gprpp/global_config_env.h',
+ 'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index b5ff2c622d0..ec8661b4d19 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -208,6 +208,10 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/fork.h',
+ 'src/core/lib/gprpp/global_config.h',
+ 'src/core/lib/gprpp/global_config_custom.h',
+ 'src/core/lib/gprpp/global_config_env.h',
+ 'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
@@ -250,6 +254,7 @@ Pod::Spec.new do |s|
'src/core/lib/gpr/wrap_memcpy.cc',
'src/core/lib/gprpp/arena.cc',
'src/core/lib/gprpp/fork.cc',
+ 'src/core/lib/gprpp/global_config_env.cc',
'src/core/lib/gprpp/thd_posix.cc',
'src/core/lib/gprpp/thd_windows.cc',
'src/core/lib/profiling/basic_timers.cc',
@@ -890,6 +895,10 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/fork.h',
+ 'src/core/lib/gprpp/global_config.h',
+ 'src/core/lib/gprpp/global_config_custom.h',
+ 'src/core/lib/gprpp/global_config_env.h',
+ 'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 943e0aaa1a7..59296e8e251 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -102,6 +102,10 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/arena.h )
s.files += %w( src/core/lib/gprpp/atomic.h )
s.files += %w( src/core/lib/gprpp/fork.h )
+ s.files += %w( src/core/lib/gprpp/global_config.h )
+ s.files += %w( src/core/lib/gprpp/global_config_custom.h )
+ s.files += %w( src/core/lib/gprpp/global_config_env.h )
+ s.files += %w( src/core/lib/gprpp/global_config_generic.h )
s.files += %w( src/core/lib/gprpp/manual_constructor.h )
s.files += %w( src/core/lib/gprpp/map.h )
s.files += %w( src/core/lib/gprpp/memory.h )
@@ -144,6 +148,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gpr/wrap_memcpy.cc )
s.files += %w( src/core/lib/gprpp/arena.cc )
s.files += %w( src/core/lib/gprpp/fork.cc )
+ s.files += %w( src/core/lib/gprpp/global_config_env.cc )
s.files += %w( src/core/lib/gprpp/thd_posix.cc )
s.files += %w( src/core/lib/gprpp/thd_windows.cc )
s.files += %w( src/core/lib/profiling/basic_timers.cc )
diff --git a/grpc.gyp b/grpc.gyp
index 5321658508a..14d98d003a6 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -252,6 +252,7 @@
'src/core/lib/gpr/wrap_memcpy.cc',
'src/core/lib/gprpp/arena.cc',
'src/core/lib/gprpp/fork.cc',
+ 'src/core/lib/gprpp/global_config_env.cc',
'src/core/lib/gprpp/thd_posix.cc',
'src/core/lib/gprpp/thd_windows.cc',
'src/core/lib/profiling/basic_timers.cc',
diff --git a/package.xml b/package.xml
index c3e25173349..52b954e20c6 100644
--- a/package.xml
+++ b/package.xml
@@ -107,6 +107,10 @@
+
+
+
+
@@ -149,6 +153,7 @@
+
diff --git a/src/core/ext/filters/client_channel/backup_poller.cc b/src/core/ext/filters/client_channel/backup_poller.cc
index 3e2faa57bcf..a2d45c04026 100644
--- a/src/core/ext/filters/client_channel/backup_poller.cc
+++ b/src/core/ext/filters/client_channel/backup_poller.cc
@@ -25,8 +25,8 @@
#include
#include
#include "src/core/ext/filters/client_channel/client_channel.h"
-#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/timer.h"
@@ -56,21 +56,22 @@ static backup_poller* g_poller = nullptr; // guarded by g_poller_mu
// treated as const.
static int g_poll_interval_ms = DEFAULT_POLL_INTERVAL_MS;
+GPR_GLOBAL_CONFIG_DEFINE_INT32(grpc_client_channel_backup_poll_interval_ms,
+ DEFAULT_POLL_INTERVAL_MS,
+ "Client channel backup poll interval (ms)");
+
static void init_globals() {
gpr_mu_init(&g_poller_mu);
- char* env = gpr_getenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS");
- if (env != nullptr) {
- int poll_interval_ms = gpr_parse_nonnegative_int(env);
- if (poll_interval_ms == -1) {
- gpr_log(GPR_ERROR,
- "Invalid GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS: %s, "
- "default value %d will be used.",
- env, g_poll_interval_ms);
- } else {
- g_poll_interval_ms = poll_interval_ms;
- }
+ int32_t poll_interval_ms =
+ GPR_GLOBAL_CONFIG_GET(grpc_client_channel_backup_poll_interval_ms);
+ if (poll_interval_ms < 0) {
+ gpr_log(GPR_ERROR,
+ "Invalid GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS: %d, "
+ "default value %d will be used.",
+ poll_interval_ms, g_poll_interval_ms);
+ } else {
+ g_poll_interval_ms = poll_interval_ms;
}
- gpr_free(env);
}
static void backup_poller_shutdown_unref(backup_poller* p) {
diff --git a/src/core/ext/filters/client_channel/backup_poller.h b/src/core/ext/filters/client_channel/backup_poller.h
index 8f132f968ce..e1bf4f88b2a 100644
--- a/src/core/ext/filters/client_channel/backup_poller.h
+++ b/src/core/ext/filters/client_channel/backup_poller.h
@@ -23,6 +23,9 @@
#include
#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/gprpp/global_config.h"
+
+GPR_GLOBAL_CONFIG_DECLARE_INT32(grpc_client_channel_backup_poll_interval_ms);
/* Start polling \a interested_parties periodically in the timer thread */
void grpc_client_channel_start_backup_polling(
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc b/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc
index 531ea73e9e6..4c929d00ec9 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc
@@ -20,16 +20,15 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/transport/metadata.h"
+GPR_GLOBAL_CONFIG_DEFINE_BOOL(grpc_experimental_disable_flow_control, false,
+ "Disable flow control");
+
void grpc_chttp2_plugin_init(void) {
- g_flow_control_enabled = true;
- char* env_variable = gpr_getenv("GRPC_EXPERIMENTAL_DISABLE_FLOW_CONTROL");
- if (env_variable != nullptr) {
- g_flow_control_enabled = false;
- gpr_free(env_variable);
- }
+ g_flow_control_enabled =
+ !GPR_GLOBAL_CONFIG_GET(grpc_experimental_disable_flow_control);
}
void grpc_chttp2_plugin_shutdown(void) {}
diff --git a/src/core/lib/gpr/env.h b/src/core/lib/gpr/env.h
index aec8a3166b1..5956d17fcfe 100644
--- a/src/core/lib/gpr/env.h
+++ b/src/core/lib/gpr/env.h
@@ -40,4 +40,7 @@ void gpr_setenv(const char* name, const char* value);
level of logging. So DO NOT USE THIS. */
const char* gpr_getenv_silent(const char* name, char** dst);
+/* Deletes the variable name from the environment. */
+void gpr_unsetenv(const char* name);
+
#endif /* GRPC_CORE_LIB_GPR_ENV_H */
diff --git a/src/core/lib/gpr/env_linux.cc b/src/core/lib/gpr/env_linux.cc
index fadc42f22f1..e84a9f6064c 100644
--- a/src/core/lib/gpr/env_linux.cc
+++ b/src/core/lib/gpr/env_linux.cc
@@ -79,4 +79,9 @@ void gpr_setenv(const char* name, const char* value) {
GPR_ASSERT(res == 0);
}
+void gpr_unsetenv(const char* name) {
+ int res = unsetenv(name);
+ GPR_ASSERT(res == 0);
+}
+
#endif /* GPR_LINUX_ENV */
diff --git a/src/core/lib/gpr/env_posix.cc b/src/core/lib/gpr/env_posix.cc
index 599f85aa72b..30ddc50f682 100644
--- a/src/core/lib/gpr/env_posix.cc
+++ b/src/core/lib/gpr/env_posix.cc
@@ -44,4 +44,9 @@ void gpr_setenv(const char* name, const char* value) {
GPR_ASSERT(res == 0);
}
+void gpr_unsetenv(const char* name) {
+ int res = unsetenv(name);
+ GPR_ASSERT(res == 0);
+}
+
#endif /* GPR_POSIX_ENV */
diff --git a/src/core/lib/gpr/env_windows.cc b/src/core/lib/gpr/env_windows.cc
index cf8ed60d8f6..72850a9587d 100644
--- a/src/core/lib/gpr/env_windows.cc
+++ b/src/core/lib/gpr/env_windows.cc
@@ -69,4 +69,11 @@ void gpr_setenv(const char* name, const char* value) {
GPR_ASSERT(res);
}
+void gpr_unsetenv(const char* name) {
+ LPTSTR tname = gpr_char_to_tchar(name);
+ BOOL res = SetEnvironmentVariable(tname, NULL);
+ gpr_free(tname);
+ GPR_ASSERT(res);
+}
+
#endif /* GPR_WINDOWS_ENV */
diff --git a/src/core/lib/gpr/string.cc b/src/core/lib/gpr/string.cc
index 0a76fc1f54a..31d5fdee5be 100644
--- a/src/core/lib/gpr/string.cc
+++ b/src/core/lib/gpr/string.cc
@@ -332,16 +332,22 @@ void* gpr_memrchr(const void* s, int c, size_t n) {
return nullptr;
}
-bool gpr_is_true(const char* s) {
- size_t i;
+bool gpr_parse_bool_value(const char* s, bool* dst) {
+ const char* kTrue[] = {"1", "t", "true", "y", "yes"};
+ const char* kFalse[] = {"0", "f", "false", "n", "no"};
+ static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal");
+
if (s == nullptr) {
return false;
}
- static const char* truthy[] = {"yes", "true", "1"};
- for (i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
- if (0 == gpr_stricmp(s, truthy[i])) {
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(kTrue); ++i) {
+ if (gpr_stricmp(s, kTrue[i]) == 0) {
+ *dst = true;
+ return true;
+ } else if (gpr_stricmp(s, kFalse[i]) == 0) {
+ *dst = false;
return true;
}
}
- return false;
+ return false; // didn't match a legal input
}
diff --git a/src/core/lib/gpr/string.h b/src/core/lib/gpr/string.h
index ce51fe46321..c5efcec3bb1 100644
--- a/src/core/lib/gpr/string.h
+++ b/src/core/lib/gpr/string.h
@@ -113,7 +113,9 @@ int gpr_stricmp(const char* a, const char* b);
void* gpr_memrchr(const void* s, int c, size_t n);
-/** Return true if lower(s) equals "true", "yes" or "1", otherwise false. */
-bool gpr_is_true(const char* s);
+/* Try to parse given string into a boolean value.
+ When parsed successfully, dst will have the value and returns true.
+ Otherwise, it returns false. */
+bool gpr_parse_bool_value(const char* value, bool* dst);
#endif /* GRPC_CORE_LIB_GPR_STRING_H */
diff --git a/src/core/lib/gprpp/global_config.h b/src/core/lib/gprpp/global_config.h
new file mode 100644
index 00000000000..a1bbf07564c
--- /dev/null
+++ b/src/core/lib/gprpp/global_config.h
@@ -0,0 +1,87 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * 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_LIB_GPRPP_GLOBAL_CONFIG_H
+#define GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_H
+
+#include
+
+#include
+
+// --------------------------------------------------------------------
+// How to use global configuration variables:
+//
+// Defining config variables of a specified type:
+// GPR_GLOBAL_CONFIG_DEFINE_*TYPE*(name, default_value, help);
+//
+// Supported TYPEs: BOOL, INT32, STRING
+//
+// It's recommended to use lowercase letters for 'name' like
+// regular variables. The builtin configuration system uses
+// environment variable and the name is converted to uppercase
+// when looking up the value. For example,
+// GPR_GLOBAL_CONFIG_DEFINE(grpc_latency) looks up the value with the
+// name, "GRPC_LATENCY".
+//
+// The variable initially has the specified 'default_value'
+// which must be an expression convertible to 'Type'.
+// 'default_value' may be evaluated 0 or more times,
+// and at an unspecified time; keep it
+// simple and usually free of side-effects.
+//
+// GPR_GLOBAL_CONFIG_DEFINE_*TYPE* should not be called in a C++ header.
+// It should be called at the top-level (outside any namespaces)
+// in a .cc file.
+//
+// Getting the variables:
+// GPR_GLOBAL_CONFIG_GET(name)
+//
+// If error happens during getting variables, error messages will
+// be logged and default value will be returned.
+//
+// Setting the variables with new value:
+// GPR_GLOBAL_CONFIG_SET(name, new_value)
+//
+// Declaring config variables for other modules to access:
+// GPR_GLOBAL_CONFIG_DECLARE_*TYPE*(name)
+
+// --------------------------------------------------------------------
+// How to customize the global configuration system:
+//
+// How to read and write configuration value can be customized.
+// Builtin system uses environment variables but it can be extended to
+// support command-line flag, file, etc.
+//
+// To customize it, following macros should be redefined.
+//
+// GPR_GLOBAL_CONFIG_DEFINE_BOOL
+// GPR_GLOBAL_CONFIG_DEFINE_INT32
+// GPR_GLOBAL_CONFIG_DEFINE_STRING
+//
+// These macros should define functions for getting and setting variable.
+// For example, GPR_GLOBAL_CONFIG_DEFINE_BOOL(test, ...) would define two
+// functions.
+//
+// bool gpr_global_config_get_test();
+// void gpr_global_config_set_test(bool value);
+
+#include "src/core/lib/gprpp/global_config_env.h"
+
+#include "src/core/lib/gprpp/global_config_custom.h"
+
+#endif /* GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_H */
diff --git a/src/core/lib/gprpp/global_config_custom.h b/src/core/lib/gprpp/global_config_custom.h
new file mode 100644
index 00000000000..dd011fb34bf
--- /dev/null
+++ b/src/core/lib/gprpp/global_config_custom.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * 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_LIB_GPRPP_GLOBAL_CONFIG_CUSTOM_H
+#define GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_CUSTOM_H
+
+// This is a placeholder for custom global configuration implementaion.
+// To use the custom one, please define following macros here.
+//
+// GPR_GLOBAL_CONFIG_DEFINE_BOOL
+// GPR_GLOBAL_CONFIG_DEFINE_INT32
+// GPR_GLOBAL_CONFIG_DEFINE_STRING
+
+#endif /* GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_CUSTOM_H */
diff --git a/src/core/lib/gprpp/global_config_env.cc b/src/core/lib/gprpp/global_config_env.cc
new file mode 100644
index 00000000000..fb14805d01b
--- /dev/null
+++ b/src/core/lib/gprpp/global_config_env.cc
@@ -0,0 +1,135 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * 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
+
+#include "src/core/lib/gprpp/global_config_env.h"
+
+#include
+#include
+#include
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
+
+#include
+#include
+
+namespace grpc_core {
+
+namespace {
+
+void DefaultGlobalConfigEnvErrorFunction(const char* error_message) {
+ gpr_log(GPR_ERROR, "%s", error_message);
+}
+
+GlobalConfigEnvErrorFunctionType g_global_config_env_error_func =
+ DefaultGlobalConfigEnvErrorFunction;
+
+void LogParsingError(const char* name, const char* value) {
+ char* error_message;
+ gpr_asprintf(&error_message,
+ "Illegal value '%s' specified for environment variable '%s'",
+ value, name);
+ (*g_global_config_env_error_func)(error_message);
+ gpr_free(error_message);
+}
+
+} // namespace
+
+void SetGlobalConfigEnvErrorFunction(GlobalConfigEnvErrorFunctionType func) {
+ g_global_config_env_error_func = func;
+}
+
+UniquePtr GlobalConfigEnv::GetValue() {
+ return UniquePtr(gpr_getenv(GetName()));
+}
+
+void GlobalConfigEnv::SetValue(const char* value) {
+ gpr_setenv(GetName(), value);
+}
+
+void GlobalConfigEnv::Unset() { gpr_unsetenv(GetName()); }
+
+char* GlobalConfigEnv::GetName() {
+ // This makes sure that name_ is in a canonical form having uppercase
+ // letters. This is okay to be called serveral times.
+ for (char* c = name_; *c != 0; ++c) {
+ *c = toupper(*c);
+ }
+ return name_;
+}
+static_assert(std::is_trivially_destructible::value,
+ "GlobalConfigEnvBool needs to be trivially destructible.");
+
+bool GlobalConfigEnvBool::Get() {
+ UniquePtr str = GetValue();
+ if (str == nullptr) {
+ return default_value_;
+ }
+ // parsing given value string.
+ bool result = false;
+ if (!gpr_parse_bool_value(str.get(), &result)) {
+ LogParsingError(GetName(), str.get());
+ result = default_value_;
+ }
+ return result;
+}
+
+void GlobalConfigEnvBool::Set(bool value) {
+ SetValue(value ? "true" : "false");
+}
+
+static_assert(std::is_trivially_destructible::value,
+ "GlobalConfigEnvInt32 needs to be trivially destructible.");
+
+int32_t GlobalConfigEnvInt32::Get() {
+ UniquePtr str = GetValue();
+ if (str == nullptr) {
+ return default_value_;
+ }
+ // parsing given value string.
+ char* end = str.get();
+ long result = strtol(str.get(), &end, 10);
+ if (*end != 0) {
+ LogParsingError(GetName(), str.get());
+ result = default_value_;
+ }
+ return static_cast(result);
+}
+
+void GlobalConfigEnvInt32::Set(int32_t value) {
+ char buffer[GPR_LTOA_MIN_BUFSIZE];
+ gpr_ltoa(value, buffer);
+ SetValue(buffer);
+}
+
+static_assert(std::is_trivially_destructible::value,
+ "GlobalConfigEnvString needs to be trivially destructible.");
+
+UniquePtr GlobalConfigEnvString::Get() {
+ UniquePtr str = GetValue();
+ if (str == nullptr) {
+ return UniquePtr(gpr_strdup(default_value_));
+ }
+ return str;
+}
+
+void GlobalConfigEnvString::Set(const char* value) { SetValue(value); }
+
+} // namespace grpc_core
diff --git a/src/core/lib/gprpp/global_config_env.h b/src/core/lib/gprpp/global_config_env.h
new file mode 100644
index 00000000000..3d3038895d3
--- /dev/null
+++ b/src/core/lib/gprpp/global_config_env.h
@@ -0,0 +1,131 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * 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_LIB_GPRPP_GLOBAL_CONFIG_ENV_H
+#define GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_ENV_H
+
+#include
+
+#include "src/core/lib/gprpp/global_config_generic.h"
+#include "src/core/lib/gprpp/memory.h"
+
+namespace grpc_core {
+
+typedef void (*GlobalConfigEnvErrorFunctionType)(const char* error_message);
+
+/*
+ * Set global_config_env_error_function which is called when config system
+ * encounters errors such as parsing error. What the default function does
+ * is logging error message.
+ */
+void SetGlobalConfigEnvErrorFunction(GlobalConfigEnvErrorFunctionType func);
+
+// Base class for all classes to access environment variables.
+class GlobalConfigEnv {
+ protected:
+ // `name` should be writable and alive after constructor is called.
+ constexpr explicit GlobalConfigEnv(char* name) : name_(name) {}
+
+ public:
+ // Returns the value of `name` variable.
+ UniquePtr GetValue();
+
+ // Sets the value of `name` variable.
+ void SetValue(const char* value);
+
+ // Unsets `name` variable.
+ void Unset();
+
+ protected:
+ char* GetName();
+
+ private:
+ char* name_;
+};
+
+class GlobalConfigEnvBool : public GlobalConfigEnv {
+ public:
+ constexpr GlobalConfigEnvBool(char* name, bool default_value)
+ : GlobalConfigEnv(name), default_value_(default_value) {}
+
+ bool Get();
+ void Set(bool value);
+
+ private:
+ bool default_value_;
+};
+
+class GlobalConfigEnvInt32 : public GlobalConfigEnv {
+ public:
+ constexpr GlobalConfigEnvInt32(char* name, int32_t default_value)
+ : GlobalConfigEnv(name), default_value_(default_value) {}
+
+ int32_t Get();
+ void Set(int32_t value);
+
+ private:
+ int32_t default_value_;
+};
+
+class GlobalConfigEnvString : public GlobalConfigEnv {
+ public:
+ constexpr GlobalConfigEnvString(char* name, const char* default_value)
+ : GlobalConfigEnv(name), default_value_(default_value) {}
+
+ UniquePtr Get();
+ void Set(const char* value);
+
+ private:
+ const char* default_value_;
+};
+
+} // namespace grpc_core
+
+// Macros for defining global config instances using environment variables.
+// This defines a GlobalConfig*Type* instance with arguments for
+// mutable variable name and default value.
+// Mutable name (g_env_str_##name) is here for having an array
+// for the canonical name without dynamic allocation.
+// `help` argument is ignored for this implementation.
+
+#define GPR_GLOBAL_CONFIG_DEFINE_BOOL(name, default_value, help) \
+ static char g_env_str_##name[] = #name; \
+ static ::grpc_core::GlobalConfigEnvBool g_env_##name(g_env_str_##name, \
+ default_value); \
+ bool gpr_global_config_get_##name() { return g_env_##name.Get(); } \
+ void gpr_global_config_set_##name(bool value) { g_env_##name.Set(value); }
+
+#define GPR_GLOBAL_CONFIG_DEFINE_INT32(name, default_value, help) \
+ static char g_env_str_##name[] = #name; \
+ static ::grpc_core::GlobalConfigEnvInt32 g_env_##name(g_env_str_##name, \
+ default_value); \
+ int32_t gpr_global_config_get_##name() { return g_env_##name.Get(); } \
+ void gpr_global_config_set_##name(int32_t value) { g_env_##name.Set(value); }
+
+#define GPR_GLOBAL_CONFIG_DEFINE_STRING(name, default_value, help) \
+ static char g_env_str_##name[] = #name; \
+ static ::grpc_core::GlobalConfigEnvString g_env_##name(g_env_str_##name, \
+ default_value); \
+ ::grpc_core::UniquePtr gpr_global_config_get_##name() { \
+ return g_env_##name.Get(); \
+ } \
+ void gpr_global_config_set_##name(const char* value) { \
+ g_env_##name.Set(value); \
+ }
+
+#endif /* GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_ENV_H */
diff --git a/src/core/lib/gprpp/global_config_generic.h b/src/core/lib/gprpp/global_config_generic.h
new file mode 100644
index 00000000000..d3e3e2a2dbe
--- /dev/null
+++ b/src/core/lib/gprpp/global_config_generic.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * 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_LIB_GPRPP_GLOBAL_CONFIG_GENERIC_H
+#define GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_GENERIC_H
+
+#include
+
+#include "src/core/lib/gprpp/memory.h"
+
+#include
+
+#define GPR_GLOBAL_CONFIG_GET(name) gpr_global_config_get_##name()
+
+#define GPR_GLOBAL_CONFIG_SET(name, value) gpr_global_config_set_##name(value)
+
+#define GPR_GLOBAL_CONFIG_DECLARE_BOOL(name) \
+ extern bool gpr_global_config_get_##name(); \
+ extern void gpr_global_config_set_##name(bool value)
+
+#define GPR_GLOBAL_CONFIG_DECLARE_INT32(name) \
+ extern int32_t gpr_global_config_get_##name(); \
+ extern void gpr_global_config_set_##name(int32_t value)
+
+#define GPR_GLOBAL_CONFIG_DECLARE_STRING(name) \
+ extern grpc_core::UniquePtr gpr_global_config_get_##name(); \
+ extern void gpr_global_config_set_##name(const char* value)
+
+#endif /* GRPC_CORE_LIB_GPRPP_GLOBAL_CONFIG_GENERIC_H */
diff --git a/src/core/lib/iomgr/iomgr.cc b/src/core/lib/iomgr/iomgr.cc
index 0fbfcfce04f..fd011788a06 100644
--- a/src/core/lib/iomgr/iomgr.cc
+++ b/src/core/lib/iomgr/iomgr.cc
@@ -29,9 +29,9 @@
#include
#include
-#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/buffer_list.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@@ -41,6 +41,9 @@
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/timer_manager.h"
+GPR_GLOBAL_CONFIG_DEFINE_BOOL(grpc_abort_on_leaks, false,
+ "Abort when leak is found");
+
static gpr_mu g_mu;
static gpr_cv g_rcv;
static int g_shutdown;
@@ -186,8 +189,5 @@ void grpc_iomgr_unregister_object(grpc_iomgr_object* obj) {
}
bool grpc_iomgr_abort_on_leaks(void) {
- char* env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
- bool should_we = gpr_is_true(env);
- gpr_free(env);
- return should_we;
+ return GPR_GLOBAL_CONFIG_GET(grpc_abort_on_leaks);
}
diff --git a/src/core/lib/security/security_connector/ssl_utils.cc b/src/core/lib/security/security_connector/ssl_utils.cc
index c9af5ca6ad0..1eefff6fe24 100644
--- a/src/core/lib/security/security_connector/ssl_utils.cc
+++ b/src/core/lib/security/security_connector/ssl_utils.cc
@@ -30,6 +30,7 @@
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/host_port.h"
#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/context/security_context.h"
@@ -47,9 +48,8 @@ static const char* installed_roots_path =
/** Environment variable used as a flag to enable/disable loading system root
certificates from the OS trust store. */
-#ifndef GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR
-#define GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_NOT_USE_SYSTEM_SSL_ROOTS"
-#endif
+GPR_GLOBAL_CONFIG_DEFINE_BOOL(grpc_not_use_system_ssl_roots, false,
+ "Disable loading system root certificates.");
#ifndef TSI_OPENSSL_ALPN_SUPPORT
#define TSI_OPENSSL_ALPN_SUPPORT 1
@@ -428,10 +428,8 @@ const char* DefaultSslRootStore::GetPemRootCerts() {
grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
grpc_slice result = grpc_empty_slice();
- char* not_use_system_roots_env_value =
- gpr_getenv(GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR);
- const bool not_use_system_roots = gpr_is_true(not_use_system_roots_env_value);
- gpr_free(not_use_system_roots_env_value);
+ const bool not_use_system_roots =
+ GPR_GLOBAL_CONFIG_GET(grpc_not_use_system_ssl_roots);
// First try to load the roots from the environment.
char* default_root_certs_path =
gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 2e358f9c1ef..615bf4ee0dc 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -53,6 +53,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/gpr/wrap_memcpy.cc',
'src/core/lib/gprpp/arena.cc',
'src/core/lib/gprpp/fork.cc',
+ 'src/core/lib/gprpp/global_config_env.cc',
'src/core/lib/gprpp/thd_posix.cc',
'src/core/lib/gprpp/thd_windows.cc',
'src/core/lib/profiling/basic_timers.cc',
diff --git a/test/core/gpr/env_test.cc b/test/core/gpr/env_test.cc
index a8206bd3cfd..3883a5df997 100644
--- a/test/core/gpr/env_test.cc
+++ b/test/core/gpr/env_test.cc
@@ -42,8 +42,22 @@ static void test_setenv_getenv(void) {
gpr_free(retrieved_value);
}
+static void test_unsetenv(void) {
+ const char* name = "FOO";
+ const char* value = "BAR";
+ char* retrieved_value;
+
+ LOG_TEST_NAME("test_unsetenv");
+
+ gpr_setenv(name, value);
+ gpr_unsetenv(name);
+ retrieved_value = gpr_getenv(name);
+ GPR_ASSERT(retrieved_value == nullptr);
+}
+
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
test_setenv_getenv();
+ test_unsetenv();
return 0;
}
diff --git a/test/core/gpr/string_test.cc b/test/core/gpr/string_test.cc
index 7da7b18778b..5e3ed9d5dfd 100644
--- a/test/core/gpr/string_test.cc
+++ b/test/core/gpr/string_test.cc
@@ -279,19 +279,20 @@ static void test_memrchr(void) {
GPR_ASSERT(0 == strcmp((const char*)gpr_memrchr("hello", 'l', 5), "lo"));
}
-static void test_is_true(void) {
- LOG_TEST_NAME("test_is_true");
-
- GPR_ASSERT(true == gpr_is_true("True"));
- GPR_ASSERT(true == gpr_is_true("true"));
- GPR_ASSERT(true == gpr_is_true("TRUE"));
- GPR_ASSERT(true == gpr_is_true("Yes"));
- GPR_ASSERT(true == gpr_is_true("yes"));
- GPR_ASSERT(true == gpr_is_true("YES"));
- GPR_ASSERT(true == gpr_is_true("1"));
- GPR_ASSERT(false == gpr_is_true(nullptr));
- GPR_ASSERT(false == gpr_is_true(""));
- GPR_ASSERT(false == gpr_is_true("0"));
+static void test_parse_bool_value(void) {
+ LOG_TEST_NAME("test_parse_bool_value");
+
+ bool ret;
+ GPR_ASSERT(true == gpr_parse_bool_value("truE", &ret) && true == ret);
+ GPR_ASSERT(true == gpr_parse_bool_value("falsE", &ret) && false == ret);
+ GPR_ASSERT(true == gpr_parse_bool_value("1", &ret) && true == ret);
+ GPR_ASSERT(true == gpr_parse_bool_value("0", &ret) && false == ret);
+ GPR_ASSERT(true == gpr_parse_bool_value("Yes", &ret) && true == ret);
+ GPR_ASSERT(true == gpr_parse_bool_value("No", &ret) && false == ret);
+ GPR_ASSERT(true == gpr_parse_bool_value("Y", &ret) && true == ret);
+ GPR_ASSERT(true == gpr_parse_bool_value("N", &ret) && false == ret);
+ GPR_ASSERT(false == gpr_parse_bool_value(nullptr, &ret));
+ GPR_ASSERT(false == gpr_parse_bool_value("", &ret));
}
int main(int argc, char** argv) {
@@ -307,6 +308,6 @@ int main(int argc, char** argv) {
test_leftpad();
test_stricmp();
test_memrchr();
- test_is_true();
+ test_parse_bool_value();
return 0;
}
diff --git a/test/core/gprpp/BUILD b/test/core/gprpp/BUILD
index 4665827e10f..cd3232addfd 100644
--- a/test/core/gprpp/BUILD
+++ b/test/core/gprpp/BUILD
@@ -28,6 +28,32 @@ grpc_cc_test(
],
)
+grpc_cc_test(
+ name = "global_config_test",
+ srcs = ["global_config_test.cc"],
+ external_deps = [
+ "gtest",
+ ],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
+grpc_cc_test(
+ name = "global_config_env_test",
+ srcs = ["global_config_env_test.cc"],
+ external_deps = [
+ "gtest",
+ ],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
grpc_cc_test(
name = "manual_constructor_test",
srcs = ["manual_constructor_test.cc"],
diff --git a/test/core/gprpp/global_config_env_test.cc b/test/core/gprpp/global_config_env_test.cc
new file mode 100644
index 00000000000..74905d3b07c
--- /dev/null
+++ b/test/core/gprpp/global_config_env_test.cc
@@ -0,0 +1,130 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * 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
+#include
+
+#include
+
+#include
+#include
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gprpp/global_config_env.h"
+#include "src/core/lib/gprpp/memory.h"
+
+namespace {
+
+bool g_config_error_function_called;
+
+void ClearConfigErrorCalled() { g_config_error_function_called = false; }
+
+bool IsConfigErrorCalled() { return g_config_error_function_called; }
+
+// This function is for preventing the program from invoking
+// an error handler due to configuration error and
+// make test routines know whether there is error.
+void FakeConfigErrorFunction(const char* error_message) {
+ g_config_error_function_called = true;
+}
+
+class GlobalConfigEnvTest : public ::testing::Test {
+ protected:
+ void SetUp() override { ClearConfigErrorCalled(); }
+ void TearDown() override { EXPECT_FALSE(IsConfigErrorCalled()); }
+};
+
+} // namespace
+
+GPR_GLOBAL_CONFIG_DEFINE_BOOL(bool_var, true, "");
+GPR_GLOBAL_CONFIG_DEFINE_INT32(int32_var, 1234, "");
+GPR_GLOBAL_CONFIG_DEFINE_STRING(string_var, "Apple", "");
+
+TEST_F(GlobalConfigEnvTest, BoolWithEnvTest) {
+ const char* bool_var_name = "BOOL_VAR";
+
+ gpr_unsetenv(bool_var_name);
+ EXPECT_TRUE(GPR_GLOBAL_CONFIG_GET(bool_var));
+
+ gpr_setenv(bool_var_name, "true");
+ EXPECT_TRUE(GPR_GLOBAL_CONFIG_GET(bool_var));
+
+ gpr_setenv(bool_var_name, "false");
+ EXPECT_FALSE(GPR_GLOBAL_CONFIG_GET(bool_var));
+
+ EXPECT_FALSE(IsConfigErrorCalled());
+
+ gpr_setenv(bool_var_name, "");
+ GPR_GLOBAL_CONFIG_GET(bool_var);
+ EXPECT_TRUE(IsConfigErrorCalled());
+ ClearConfigErrorCalled();
+
+ gpr_setenv(bool_var_name, "!");
+ GPR_GLOBAL_CONFIG_GET(bool_var);
+ EXPECT_TRUE(IsConfigErrorCalled());
+ ClearConfigErrorCalled();
+}
+
+TEST_F(GlobalConfigEnvTest, Int32WithEnvTest) {
+ const char* int32_var_name = "INT32_VAR";
+
+ gpr_unsetenv(int32_var_name);
+ EXPECT_EQ(1234, GPR_GLOBAL_CONFIG_GET(int32_var));
+
+ gpr_setenv(int32_var_name, "0");
+ EXPECT_EQ(0, GPR_GLOBAL_CONFIG_GET(int32_var));
+
+ gpr_setenv(int32_var_name, "-123456789");
+ EXPECT_EQ(-123456789, GPR_GLOBAL_CONFIG_GET(int32_var));
+
+ gpr_setenv(int32_var_name, "123456789");
+ EXPECT_EQ(123456789, GPR_GLOBAL_CONFIG_GET(int32_var));
+
+ EXPECT_FALSE(IsConfigErrorCalled());
+
+ gpr_setenv(int32_var_name, "-1AB");
+ GPR_GLOBAL_CONFIG_GET(int32_var);
+ EXPECT_TRUE(IsConfigErrorCalled());
+ ClearConfigErrorCalled();
+}
+
+TEST_F(GlobalConfigEnvTest, StringWithEnvTest) {
+ const char* string_var_name = "STRING_VAR";
+ grpc_core::UniquePtr value;
+
+ gpr_unsetenv(string_var_name);
+ value = GPR_GLOBAL_CONFIG_GET(string_var);
+ EXPECT_EQ(0, strcmp(value.get(), "Apple"));
+
+ gpr_setenv(string_var_name, "Banana");
+ value = GPR_GLOBAL_CONFIG_GET(string_var);
+ EXPECT_EQ(0, strcmp(value.get(), "Banana"));
+
+ gpr_setenv(string_var_name, "");
+ value = GPR_GLOBAL_CONFIG_GET(string_var);
+ EXPECT_EQ(0, strcmp(value.get(), ""));
+}
+
+int main(int argc, char** argv) {
+ // Not to abort the test when parsing error happens.
+ grpc_core::SetGlobalConfigEnvErrorFunction(&FakeConfigErrorFunction);
+
+ ::testing::InitGoogleTest(&argc, argv);
+ int ret = RUN_ALL_TESTS();
+ return ret;
+}
diff --git a/test/core/gprpp/global_config_test.cc b/test/core/gprpp/global_config_test.cc
new file mode 100644
index 00000000000..7da78b690b1
--- /dev/null
+++ b/test/core/gprpp/global_config_test.cc
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2019 gRPC authors.
+ *
+ * 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
+#include
+
+#include
+
+#include
+#include
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gprpp/global_config.h"
+#include "src/core/lib/gprpp/memory.h"
+
+GPR_GLOBAL_CONFIG_DECLARE_BOOL(bool_var);
+
+GPR_GLOBAL_CONFIG_DEFINE_BOOL(bool_var, false, "");
+GPR_GLOBAL_CONFIG_DEFINE_INT32(int32_var, 0, "");
+GPR_GLOBAL_CONFIG_DEFINE_STRING(string_var, "", "");
+
+TEST(GlobalConfigTest, BoolTest) {
+ EXPECT_FALSE(GPR_GLOBAL_CONFIG_GET(bool_var));
+ GPR_GLOBAL_CONFIG_SET(bool_var, true);
+ EXPECT_TRUE(GPR_GLOBAL_CONFIG_GET(bool_var));
+}
+
+TEST(GlobalConfigTest, Int32Test) {
+ EXPECT_EQ(0, GPR_GLOBAL_CONFIG_GET(int32_var));
+ GPR_GLOBAL_CONFIG_SET(int32_var, 1024);
+ EXPECT_EQ(1024, GPR_GLOBAL_CONFIG_GET(int32_var));
+}
+
+TEST(GlobalConfigTest, StringTest) {
+ grpc_core::UniquePtr value;
+
+ value = GPR_GLOBAL_CONFIG_GET(string_var);
+ EXPECT_EQ(0, strcmp(value.get(), ""));
+
+ GPR_GLOBAL_CONFIG_SET(string_var, "Test");
+
+ value = GPR_GLOBAL_CONFIG_GET(string_var);
+ EXPECT_EQ(0, strcmp(value.get(), "Test"));
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int ret = RUN_ALL_TESTS();
+ return ret;
+}
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index e09f54dcc3f..840d668e0d8 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -32,6 +32,7 @@
#include
#include
+#include "src/core/ext/filters/client_channel/backup_poller.h"
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/tls.h"
#include "src/core/lib/iomgr/port.h"
@@ -1883,7 +1884,7 @@ INSTANTIATE_TEST_CASE_P(AsyncEnd2endServerTryCancel,
int main(int argc, char** argv) {
// Change the backup poll interval from 5s to 100ms to speed up the
// ReconnectChannel test
- gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "100");
+ GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 100);
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc
index 6623a2ff55f..ca20ebbaeee 100644
--- a/test/cpp/end2end/client_lb_end2end_test.cc
+++ b/test/cpp/end2end/client_lb_end2end_test.cc
@@ -37,13 +37,13 @@
#include
#include
+#include "src/core/ext/filters/client_channel/backup_poller.h"
#include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/tcp_client.h"
@@ -142,7 +142,7 @@ class ClientLbEnd2endTest : public ::testing::Test {
grpc_fake_transport_security_credentials_create())) {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
- gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "1");
+ GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
}
void SetUp() override {
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index fb951fd44e6..a2b9ebe7197 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -34,6 +34,7 @@
#include
#include
+#include "src/core/ext/filters/client_channel/backup_poller.h"
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/security/credentials/credentials.h"
@@ -2104,7 +2105,7 @@ INSTANTIATE_TEST_CASE_P(
} // namespace grpc
int main(int argc, char** argv) {
- gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "200");
+ GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 200);
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc
index bd915b04eee..f93e2548c8e 100644
--- a/test/cpp/end2end/grpclb_end2end_test.cc
+++ b/test/cpp/end2end/grpclb_end2end_test.cc
@@ -34,11 +34,11 @@
#include
#include
+#include "src/core/ext/filters/client_channel/backup_poller.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/filters/client_channel/service_config.h"
-#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
@@ -375,7 +375,7 @@ class GrpclbEnd2endTest : public ::testing::Test {
client_load_reporting_interval_seconds) {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
- gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "1");
+ GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
}
void SetUp() override {
diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc
index 2952c194d48..d6f2685642c 100644
--- a/test/cpp/end2end/xds_end2end_test.cc
+++ b/test/cpp/end2end/xds_end2end_test.cc
@@ -33,6 +33,7 @@
#include
#include
+#include "src/core/ext/filters/client_channel/backup_poller.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include "src/core/ext/filters/client_channel/server_address.h"
@@ -370,7 +371,7 @@ class XdsEnd2endTest : public ::testing::Test {
client_load_reporting_interval_seconds) {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
- gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "1");
+ GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
}
void SetUp() override {
diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc
index 2e54993a31c..4d1beb7ec37 100644
--- a/test/cpp/naming/resolver_component_test.cc
+++ b/test/cpp/naming/resolver_component_test.cc
@@ -146,8 +146,9 @@ vector ParseExpectedAddrs(std::string expected_addrs) {
expected_addrs = expected_addrs.substr(next_comma + 1, std::string::npos);
// get the next is_balancer 'bool' associated with this address
size_t next_semicolon = expected_addrs.find(';');
- bool is_balancer =
- gpr_is_true(expected_addrs.substr(0, next_semicolon).c_str());
+ bool is_balancer = false;
+ gpr_parse_bool_value(expected_addrs.substr(0, next_semicolon).c_str(),
+ &is_balancer);
out.emplace_back(GrpcLBAddress(next_addr, is_balancer));
if (next_semicolon == std::string::npos) {
break;
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 357efa0d684..bc2a32d3cfd 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1086,6 +1086,10 @@ src/core/lib/gprpp/arena.h \
src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/debug_location.h \
src/core/lib/gprpp/fork.h \
+src/core/lib/gprpp/global_config.h \
+src/core/lib/gprpp/global_config_custom.h \
+src/core/lib/gprpp/global_config_env.h \
+src/core/lib/gprpp/global_config_generic.h \
src/core/lib/gprpp/inlined_vector.h \
src/core/lib/gprpp/manual_constructor.h \
src/core/lib/gprpp/map.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 3a9951b0364..870d6348df0 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1165,6 +1165,11 @@ src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/debug_location.h \
src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/fork.h \
+src/core/lib/gprpp/global_config.h \
+src/core/lib/gprpp/global_config_custom.h \
+src/core/lib/gprpp/global_config_env.cc \
+src/core/lib/gprpp/global_config_env.h \
+src/core/lib/gprpp/global_config_generic.h \
src/core/lib/gprpp/inlined_vector.h \
src/core/lib/gprpp/manual_constructor.h \
src/core/lib/gprpp/map.h \
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 9778343cd94..e07bb48675a 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -3662,6 +3662,36 @@
"third_party": false,
"type": "target"
},
+ {
+ "deps": [
+ "gpr",
+ "grpc_test_util_unsecure"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c++",
+ "name": "global_config_env_test",
+ "src": [
+ "test/core/gprpp/global_config_env_test.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
+ "grpc_test_util_unsecure"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c++",
+ "name": "global_config_test",
+ "src": [
+ "test/core/gprpp/global_config_test.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
{
"deps": [
"gpr",
@@ -8019,6 +8049,7 @@
"src/core/lib/gpr/wrap_memcpy.cc",
"src/core/lib/gprpp/arena.cc",
"src/core/lib/gprpp/fork.cc",
+ "src/core/lib/gprpp/global_config_env.cc",
"src/core/lib/gprpp/thd_posix.cc",
"src/core/lib/gprpp/thd_windows.cc",
"src/core/lib/profiling/basic_timers.cc",
@@ -8069,6 +8100,10 @@
"src/core/lib/gprpp/arena.h",
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/fork.h",
+ "src/core/lib/gprpp/global_config.h",
+ "src/core/lib/gprpp/global_config_custom.h",
+ "src/core/lib/gprpp/global_config_env.h",
+ "src/core/lib/gprpp/global_config_generic.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/map.h",
"src/core/lib/gprpp/memory.h",
@@ -8118,6 +8153,10 @@
"src/core/lib/gprpp/arena.h",
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/fork.h",
+ "src/core/lib/gprpp/global_config.h",
+ "src/core/lib/gprpp/global_config_custom.h",
+ "src/core/lib/gprpp/global_config_env.h",
+ "src/core/lib/gprpp/global_config_generic.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/map.h",
"src/core/lib/gprpp/memory.h",
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index ec2e570bea7..8c14282acbb 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -4499,6 +4499,54 @@
],
"uses_polling": true
},
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": false,
+ "language": "c++",
+ "name": "global_config_env_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "uses_polling": false
+ },
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": false,
+ "language": "c++",
+ "name": "global_config_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "uses_polling": false
+ },
{
"args": [
"--generated_file_path=gens/src/proto/grpc/testing/"