1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 
14 #include "google/cloud/bigtable/client_options.h"
15 #include "google/cloud/bigtable/internal/client_options_defaults.h"
16 #include "google/cloud/internal/build_info.h"
17 #include "google/cloud/internal/getenv.h"
18 #include <sstream>
19 #include <thread>
20 
21 namespace {
BigtableDefaultCredentials()22 std::shared_ptr<grpc::ChannelCredentials> BigtableDefaultCredentials() {
23   auto emulator = google::cloud::internal::GetEnv("BIGTABLE_EMULATOR_HOST");
24   if (emulator.has_value()) {
25     return grpc::InsecureChannelCredentials();
26   }
27   return grpc::GoogleDefaultCredentials();
28 }
29 }  // anonymous namespace
30 
31 namespace google {
32 namespace cloud {
33 namespace bigtable {
34 inline namespace BIGTABLE_CLIENT_NS {
35 namespace internal {
36 
DefaultDataEndpoint()37 std::string DefaultDataEndpoint() {
38   auto emulator = google::cloud::internal::GetEnv("BIGTABLE_EMULATOR_HOST");
39   if (emulator.has_value()) return *std::move(emulator);
40   auto direct_path =
41       google::cloud::internal::GetEnv("GOOGLE_CLOUD_ENABLE_DIRECT_PATH");
42   if (direct_path.has_value()) {
43     std::istringstream is(*std::move(direct_path));
44     std::string token;
45     while (std::getline(is, token, ',')) {
46       if (token == "bigtable") return "directpath-bigtable.googleapis.com";
47     }
48   }
49   return "bigtable.googleapis.com";
50 }
51 
DefaultAdminEndpoint()52 std::string DefaultAdminEndpoint() {
53   auto emulator = google::cloud::internal::GetEnv("BIGTABLE_EMULATOR_HOST");
54   if (emulator.has_value()) return *std::move(emulator);
55   return "bigtableadmin.googleapis.com";
56 }
57 
DefaultInstanceAdminEndpoint()58 std::string DefaultInstanceAdminEndpoint() {
59   auto emulator =
60       google::cloud::internal::GetEnv("BIGTABLE_INSTANCE_ADMIN_EMULATOR_HOST");
61   if (emulator.has_value()) return *std::move(emulator);
62   return DefaultAdminEndpoint();
63 }
64 
65 }  // namespace internal
66 
CalculateDefaultConnectionPoolSize()67 inline std::size_t CalculateDefaultConnectionPoolSize() {
68   // For batter resource utilization and greater throughput, it is recommended
69   // to calculate the default pool size based on cores(CPU) available. However,
70   // as per C++11 documentation `std::thread::hardware_concurrency()` cannot be
71   // fully rely upon, it is only a hint and the value can be 0 if it is not
72   // well defined or not computable. Apart from CPU count, multiple channels can
73   // be opened for each CPU to increase throughput.
74   std::size_t cpu_count = std::thread::hardware_concurrency();
75   return (cpu_count > 0) ? cpu_count * BIGTABLE_CLIENT_DEFAULT_CHANNELS_PER_CPU
76                          : BIGTABLE_CLIENT_DEFAULT_CONNECTION_POOL_SIZE;
77 }
78 
ClientOptions(std::shared_ptr<grpc::ChannelCredentials> creds)79 ClientOptions::ClientOptions(std::shared_ptr<grpc::ChannelCredentials> creds)
80     : credentials_(std::move(creds)),
81       connection_pool_size_(CalculateDefaultConnectionPoolSize()),
82       data_endpoint_("bigtable.googleapis.com"),
83       admin_endpoint_("bigtableadmin.googleapis.com"),
84       instance_admin_endpoint_("bigtableadmin.googleapis.com") {
85   static std::string const kUserAgentPrefix = UserAgentPrefix();
86   channel_arguments_.SetUserAgentPrefix(kUserAgentPrefix);
87   channel_arguments_.SetMaxSendMessageSize(
88       BIGTABLE_CLIENT_DEFAULT_MAX_MESSAGE_LENGTH);
89   channel_arguments_.SetMaxReceiveMessageSize(
90       BIGTABLE_CLIENT_DEFAULT_MAX_MESSAGE_LENGTH);
91 }
92 
ClientOptions()93 ClientOptions::ClientOptions() : ClientOptions(BigtableDefaultCredentials()) {
94   data_endpoint_ = internal::DefaultDataEndpoint();
95   admin_endpoint_ = internal::DefaultAdminEndpoint();
96   instance_admin_endpoint_ = internal::DefaultInstanceAdminEndpoint();
97   auto emulator = google::cloud::internal::GetEnv("BIGTABLE_EMULATOR_HOST");
98   if (emulator.has_value()) {
99     data_endpoint_ = *emulator;
100     admin_endpoint_ = *emulator;
101     instance_admin_endpoint_ = *emulator;
102   }
103   auto instance_admin_emulator =
104       google::cloud::internal::GetEnv("BIGTABLE_INSTANCE_ADMIN_EMULATOR_HOST");
105   if (instance_admin_emulator.has_value()) {
106     instance_admin_endpoint_ = *instance_admin_emulator;
107   }
108 }
109 
110 // NOLINTNEXTLINE(readability-identifier-naming)
set_connection_pool_size(std::size_t size)111 ClientOptions& ClientOptions::set_connection_pool_size(std::size_t size) {
112   if (size == 0) {
113     connection_pool_size_ = CalculateDefaultConnectionPoolSize();
114     return *this;
115   }
116   connection_pool_size_ = size;
117   return *this;
118 }
119 
UserAgentPrefix()120 std::string ClientOptions::UserAgentPrefix() {
121   std::string agent = "gcloud-cpp/" + version_string() + " " +
122                       google::cloud::internal::compiler();
123   return agent;
124 }
125 
126 }  // namespace BIGTABLE_CLIENT_NS
127 }  // namespace bigtable
128 }  // namespace cloud
129 }  // namespace google
130