View Javadoc
1   /*
2    * Copyright 2021 TiKV Project Authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  
18  package org.tikv.common;
19  
20  import static org.tikv.common.ConfigUtils.DEF_BATCH_DELETE_CONCURRENCY;
21  import static org.tikv.common.ConfigUtils.DEF_BATCH_GET_CONCURRENCY;
22  import static org.tikv.common.ConfigUtils.DEF_BATCH_PUT_CONCURRENCY;
23  import static org.tikv.common.ConfigUtils.DEF_BATCH_SCAN_CONCURRENCY;
24  import static org.tikv.common.ConfigUtils.DEF_CHECK_HEALTH_TIMEOUT;
25  import static org.tikv.common.ConfigUtils.DEF_DB_PREFIX;
26  import static org.tikv.common.ConfigUtils.DEF_DELETE_RANGE_CONCURRENCY;
27  import static org.tikv.common.ConfigUtils.DEF_FORWARD_TIMEOUT;
28  import static org.tikv.common.ConfigUtils.DEF_GRPC_FORWARD_ENABLE;
29  import static org.tikv.common.ConfigUtils.DEF_HEALTH_CHECK_PERIOD_DURATION;
30  import static org.tikv.common.ConfigUtils.DEF_INDEX_SCAN_BATCH_SIZE;
31  import static org.tikv.common.ConfigUtils.DEF_INDEX_SCAN_CONCURRENCY;
32  import static org.tikv.common.ConfigUtils.DEF_KV_CLIENT_CONCURRENCY;
33  import static org.tikv.common.ConfigUtils.DEF_MAX_FRAME_SIZE;
34  import static org.tikv.common.ConfigUtils.DEF_METRICS_ENABLE;
35  import static org.tikv.common.ConfigUtils.DEF_METRICS_PORT;
36  import static org.tikv.common.ConfigUtils.DEF_PD_ADDRESSES;
37  import static org.tikv.common.ConfigUtils.DEF_REPLICA_READ;
38  import static org.tikv.common.ConfigUtils.DEF_SCAN_BATCH_SIZE;
39  import static org.tikv.common.ConfigUtils.DEF_SCAN_TIMEOUT;
40  import static org.tikv.common.ConfigUtils.DEF_SHOW_ROWID;
41  import static org.tikv.common.ConfigUtils.DEF_TABLE_SCAN_CONCURRENCY;
42  import static org.tikv.common.ConfigUtils.DEF_TIFLASH_ENABLE;
43  import static org.tikv.common.ConfigUtils.DEF_TIKV_API_VERSION;
44  import static org.tikv.common.ConfigUtils.DEF_TIKV_BO_REGION_MISS_BASE_IN_MS;
45  import static org.tikv.common.ConfigUtils.DEF_TIKV_CONN_RECYCLE_TIME;
46  import static org.tikv.common.ConfigUtils.DEF_TIKV_ENABLE_ATOMIC_FOR_CAS;
47  import static org.tikv.common.ConfigUtils.DEF_TIKV_GRPC_IDLE_TIMEOUT;
48  import static org.tikv.common.ConfigUtils.DEF_TIKV_GRPC_INGEST_TIMEOUT;
49  import static org.tikv.common.ConfigUtils.DEF_TIKV_GRPC_KEEPALIVE_TIME;
50  import static org.tikv.common.ConfigUtils.DEF_TIKV_GRPC_KEEPALIVE_TIMEOUT;
51  import static org.tikv.common.ConfigUtils.DEF_TIKV_GRPC_WARM_UP_TIMEOUT;
52  import static org.tikv.common.ConfigUtils.DEF_TIKV_IMPORTER_MAX_KV_BATCH_BYTES;
53  import static org.tikv.common.ConfigUtils.DEF_TIKV_IMPORTER_MAX_KV_BATCH_SIZE;
54  import static org.tikv.common.ConfigUtils.DEF_TIKV_NETWORK_MAPPING_NAME;
55  import static org.tikv.common.ConfigUtils.DEF_TIKV_PD_FIRST_GET_MEMBER_TIMEOUT;
56  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_BATCH_READ_TIMEOUT_IN_MS;
57  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_BATCH_WRITE_TIMEOUT_IN_MS;
58  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_CLEAN_TIMEOUT_IN_MS;
59  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_DEFAULT_BACKOFF_IN_MS;
60  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_READ_TIMEOUT_IN_MS;
61  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_SCAN_SLOWLOG_IN_MS;
62  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_SCAN_TIMEOUT_IN_MS;
63  import static org.tikv.common.ConfigUtils.DEF_TIKV_RAWKV_WRITE_TIMEOUT_IN_MS;
64  import static org.tikv.common.ConfigUtils.DEF_TIKV_SCAN_REGIONS_LIMIT;
65  import static org.tikv.common.ConfigUtils.DEF_TIKV_SCATTER_WAIT_SECONDS;
66  import static org.tikv.common.ConfigUtils.DEF_TIKV_TLS_ENABLE;
67  import static org.tikv.common.ConfigUtils.DEF_TIKV_TLS_RELOAD_INTERVAL;
68  import static org.tikv.common.ConfigUtils.DEF_TIKV_USE_JKS;
69  import static org.tikv.common.ConfigUtils.DEF_TIKV_WARM_UP_ENABLE;
70  import static org.tikv.common.ConfigUtils.DEF_TIMEOUT;
71  import static org.tikv.common.ConfigUtils.DEF_TiKV_CIRCUIT_BREAK_ATTEMPT_REQUEST_COUNT;
72  import static org.tikv.common.ConfigUtils.DEF_TiKV_CIRCUIT_BREAK_AVAILABILITY_ERROR_THRESHOLD_PERCENTAGE;
73  import static org.tikv.common.ConfigUtils.DEF_TiKV_CIRCUIT_BREAK_AVAILABILITY_REQUST_VOLUMN_THRESHOLD;
74  import static org.tikv.common.ConfigUtils.DEF_TiKV_CIRCUIT_BREAK_AVAILABILITY_WINDOW_IN_SECONDS;
75  import static org.tikv.common.ConfigUtils.DEF_TiKV_CIRCUIT_BREAK_ENABLE;
76  import static org.tikv.common.ConfigUtils.DEF_TiKV_CIRCUIT_BREAK_SLEEP_WINDOW_IN_SECONDS;
77  import static org.tikv.common.ConfigUtils.FOLLOWER;
78  import static org.tikv.common.ConfigUtils.HIGH_COMMAND_PRIORITY;
79  import static org.tikv.common.ConfigUtils.LEADER_AND_FOLLOWER;
80  import static org.tikv.common.ConfigUtils.LOW_COMMAND_PRIORITY;
81  import static org.tikv.common.ConfigUtils.NORMAL_COMMAND_PRIORITY;
82  import static org.tikv.common.ConfigUtils.RAW_KV_MODE;
83  import static org.tikv.common.ConfigUtils.READ_COMMITTED_ISOLATION_LEVEL;
84  import static org.tikv.common.ConfigUtils.SNAPSHOT_ISOLATION_LEVEL;
85  import static org.tikv.common.ConfigUtils.TIFLASH_ENABLE;
86  import static org.tikv.common.ConfigUtils.TIKV_API_VERSION;
87  import static org.tikv.common.ConfigUtils.TIKV_BATCH_DELETE_CONCURRENCY;
88  import static org.tikv.common.ConfigUtils.TIKV_BATCH_GET_CONCURRENCY;
89  import static org.tikv.common.ConfigUtils.TIKV_BATCH_PUT_CONCURRENCY;
90  import static org.tikv.common.ConfigUtils.TIKV_BATCH_SCAN_CONCURRENCY;
91  import static org.tikv.common.ConfigUtils.TIKV_BO_REGION_MISS_BASE_IN_MS;
92  import static org.tikv.common.ConfigUtils.TIKV_CONN_RECYCLE_TIME;
93  import static org.tikv.common.ConfigUtils.TIKV_DB_PREFIX;
94  import static org.tikv.common.ConfigUtils.TIKV_DELETE_RANGE_CONCURRENCY;
95  import static org.tikv.common.ConfigUtils.TIKV_ENABLE_ATOMIC_FOR_CAS;
96  import static org.tikv.common.ConfigUtils.TIKV_ENABLE_GRPC_FORWARD;
97  import static org.tikv.common.ConfigUtils.TIKV_GRPC_FORWARD_TIMEOUT;
98  import static org.tikv.common.ConfigUtils.TIKV_GRPC_HEALTH_CHECK_TIMEOUT;
99  import static org.tikv.common.ConfigUtils.TIKV_GRPC_IDLE_TIMEOUT;
100 import static org.tikv.common.ConfigUtils.TIKV_GRPC_INGEST_TIMEOUT;
101 import static org.tikv.common.ConfigUtils.TIKV_GRPC_KEEPALIVE_TIME;
102 import static org.tikv.common.ConfigUtils.TIKV_GRPC_KEEPALIVE_TIMEOUT;
103 import static org.tikv.common.ConfigUtils.TIKV_GRPC_MAX_FRAME_SIZE;
104 import static org.tikv.common.ConfigUtils.TIKV_GRPC_SCAN_BATCH_SIZE;
105 import static org.tikv.common.ConfigUtils.TIKV_GRPC_SCAN_TIMEOUT;
106 import static org.tikv.common.ConfigUtils.TIKV_GRPC_TIMEOUT;
107 import static org.tikv.common.ConfigUtils.TIKV_GRPC_WARM_UP_TIMEOUT;
108 import static org.tikv.common.ConfigUtils.TIKV_HEALTH_CHECK_PERIOD_DURATION;
109 import static org.tikv.common.ConfigUtils.TIKV_IMPORTER_MAX_KV_BATCH_BYTES;
110 import static org.tikv.common.ConfigUtils.TIKV_IMPORTER_MAX_KV_BATCH_SIZE;
111 import static org.tikv.common.ConfigUtils.TIKV_INDEX_SCAN_BATCH_SIZE;
112 import static org.tikv.common.ConfigUtils.TIKV_INDEX_SCAN_CONCURRENCY;
113 import static org.tikv.common.ConfigUtils.TIKV_JKS_KEY_PASSWORD;
114 import static org.tikv.common.ConfigUtils.TIKV_JKS_KEY_PATH;
115 import static org.tikv.common.ConfigUtils.TIKV_JKS_TRUST_PASSWORD;
116 import static org.tikv.common.ConfigUtils.TIKV_JKS_TRUST_PATH;
117 import static org.tikv.common.ConfigUtils.TIKV_KEY_CERT_CHAIN;
118 import static org.tikv.common.ConfigUtils.TIKV_KEY_FILE;
119 import static org.tikv.common.ConfigUtils.TIKV_KV_CLIENT_CONCURRENCY;
120 import static org.tikv.common.ConfigUtils.TIKV_KV_MODE;
121 import static org.tikv.common.ConfigUtils.TIKV_METRICS_ENABLE;
122 import static org.tikv.common.ConfigUtils.TIKV_METRICS_PORT;
123 import static org.tikv.common.ConfigUtils.TIKV_NETWORK_MAPPING_NAME;
124 import static org.tikv.common.ConfigUtils.TIKV_PD_ADDRESSES;
125 import static org.tikv.common.ConfigUtils.TIKV_PD_FIRST_GET_MEMBER_TIMEOUT;
126 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_BATCH_READ_SLOWLOG_IN_MS;
127 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_BATCH_READ_TIMEOUT_IN_MS;
128 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_BATCH_WRITE_SLOWLOG_IN_MS;
129 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_BATCH_WRITE_TIMEOUT_IN_MS;
130 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_CLEAN_TIMEOUT_IN_MS;
131 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_DEFAULT_BACKOFF_IN_MS;
132 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_READ_SLOWLOG_IN_MS;
133 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_READ_TIMEOUT_IN_MS;
134 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_SCAN_SLOWLOG_IN_MS;
135 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_SCAN_TIMEOUT_IN_MS;
136 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_SERVER_SLOWLOG_FACTOR;
137 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_WRITE_SLOWLOG_IN_MS;
138 import static org.tikv.common.ConfigUtils.TIKV_RAWKV_WRITE_TIMEOUT_IN_MS;
139 import static org.tikv.common.ConfigUtils.TIKV_REPLICA_READ;
140 import static org.tikv.common.ConfigUtils.TIKV_REQUEST_COMMAND_PRIORITY;
141 import static org.tikv.common.ConfigUtils.TIKV_REQUEST_ISOLATION_LEVEL;
142 import static org.tikv.common.ConfigUtils.TIKV_SCAN_REGIONS_LIMIT;
143 import static org.tikv.common.ConfigUtils.TIKV_SCATTER_WAIT_SECONDS;
144 import static org.tikv.common.ConfigUtils.TIKV_SHOW_ROWID;
145 import static org.tikv.common.ConfigUtils.TIKV_TABLE_SCAN_CONCURRENCY;
146 import static org.tikv.common.ConfigUtils.TIKV_TLS_ENABLE;
147 import static org.tikv.common.ConfigUtils.TIKV_TLS_RELOAD_INTERVAL;
148 import static org.tikv.common.ConfigUtils.TIKV_TRUST_CERT_COLLECTION;
149 import static org.tikv.common.ConfigUtils.TIKV_USE_JKS;
150 import static org.tikv.common.ConfigUtils.TIKV_WARM_UP_ENABLE;
151 import static org.tikv.common.ConfigUtils.TXN_KV_MODE;
152 import static org.tikv.common.ConfigUtils.TiKV_CIRCUIT_BREAK_ATTEMPT_REQUEST_COUNT;
153 import static org.tikv.common.ConfigUtils.TiKV_CIRCUIT_BREAK_AVAILABILITY_ERROR_THRESHOLD_PERCENTAGE;
154 import static org.tikv.common.ConfigUtils.TiKV_CIRCUIT_BREAK_AVAILABILITY_REQUEST_VOLUMN_THRESHOLD;
155 import static org.tikv.common.ConfigUtils.TiKV_CIRCUIT_BREAK_AVAILABILITY_WINDOW_IN_SECONDS;
156 import static org.tikv.common.ConfigUtils.TiKV_CIRCUIT_BREAK_ENABLE;
157 import static org.tikv.common.ConfigUtils.TiKV_CIRCUIT_BREAK_SLEEP_WINDOW_IN_SECONDS;
158 
159 import com.google.protobuf.ByteString;
160 import io.grpc.Metadata;
161 import java.io.IOException;
162 import java.io.InputStream;
163 import java.io.Serializable;
164 import java.net.URI;
165 import java.util.ArrayList;
166 import java.util.Arrays;
167 import java.util.List;
168 import java.util.Locale;
169 import java.util.Map;
170 import java.util.NoSuchElementException;
171 import java.util.Objects;
172 import java.util.Optional;
173 import java.util.Properties;
174 import java.util.concurrent.ConcurrentHashMap;
175 import org.slf4j.Logger;
176 import org.slf4j.LoggerFactory;
177 import org.tikv.common.pd.PDUtils;
178 import org.tikv.common.replica.ReplicaSelector;
179 import org.tikv.kvproto.Kvrpcpb;
180 import org.tikv.kvproto.Kvrpcpb.CommandPri;
181 import org.tikv.kvproto.Kvrpcpb.IsolationLevel;
182 
183 public class TiConfiguration implements Serializable {
184   private static final Logger logger = LoggerFactory.getLogger(TiConfiguration.class);
185   private static final ConcurrentHashMap<String, String> settings = new ConcurrentHashMap<>();
186   public static final Metadata.Key<String> FORWARD_META_DATA_KEY =
187       Metadata.Key.of("tikv-forwarded-host", Metadata.ASCII_STRING_MARSHALLER);
188   public static final Metadata.Key<String> PD_FORWARD_META_DATA_KEY =
189       Metadata.Key.of("pd-forwarded-host", Metadata.ASCII_STRING_MARSHALLER);
190   public static final ByteString API_V2_RAW_PREFIX = ByteString.copyFromUtf8("r");
191   public static final ByteString API_V2_TXN_PREFIX = ByteString.copyFromUtf8("x");
192 
193   static {
194     // priority: system environment > config file > default
195     loadFromSystemProperties();
196     loadFromConfigurationFile();
197     loadFromDefaultProperties();
198     listAll();
199   }
200 
201   private static void loadFromSystemProperties() {
202     for (Map.Entry<String, String> prop : Utils.getSystemProperties().entrySet()) {
203       if (prop.getKey().startsWith("tikv.")) {
204         set(prop.getKey(), prop.getValue());
205       }
206     }
207   }
208 
209   private static void loadFromConfigurationFile() {
210     try (InputStream input =
211         TiConfiguration.class
212             .getClassLoader()
213             .getResourceAsStream(ConfigUtils.TIKV_CONFIGURATION_FILENAME)) {
214       Properties properties = new Properties();
215 
216       if (input == null) {
217         logger.warn("Unable to find " + ConfigUtils.TIKV_CONFIGURATION_FILENAME);
218         return;
219       }
220 
221       logger.info("loading " + ConfigUtils.TIKV_CONFIGURATION_FILENAME);
222       properties.load(input);
223       for (String key : properties.stringPropertyNames()) {
224         if (key.startsWith("tikv.")) {
225           String value = properties.getProperty(key);
226           setIfMissing(key, value);
227         }
228       }
229     } catch (IOException e) {
230       logger.error("load config file error", e);
231     }
232   }
233 
234   private static void loadFromDefaultProperties() {
235     setIfMissing(TIKV_PD_ADDRESSES, DEF_PD_ADDRESSES);
236     setIfMissing(TIKV_GRPC_TIMEOUT, DEF_TIMEOUT);
237     setIfMissing(TIKV_GRPC_INGEST_TIMEOUT, DEF_TIKV_GRPC_INGEST_TIMEOUT);
238     setIfMissing(TIKV_GRPC_FORWARD_TIMEOUT, DEF_FORWARD_TIMEOUT);
239     setIfMissing(TIKV_GRPC_WARM_UP_TIMEOUT, DEF_TIKV_GRPC_WARM_UP_TIMEOUT);
240     setIfMissing(TIKV_PD_FIRST_GET_MEMBER_TIMEOUT, DEF_TIKV_PD_FIRST_GET_MEMBER_TIMEOUT);
241     setIfMissing(TIKV_GRPC_SCAN_TIMEOUT, DEF_SCAN_TIMEOUT);
242     setIfMissing(TIKV_GRPC_SCAN_BATCH_SIZE, DEF_SCAN_BATCH_SIZE);
243     setIfMissing(TIKV_GRPC_MAX_FRAME_SIZE, DEF_MAX_FRAME_SIZE);
244     setIfMissing(TIKV_CONN_RECYCLE_TIME, DEF_TIKV_CONN_RECYCLE_TIME);
245     setIfMissing(TIKV_TLS_RELOAD_INTERVAL, DEF_TIKV_TLS_RELOAD_INTERVAL);
246     setIfMissing(TIKV_INDEX_SCAN_BATCH_SIZE, DEF_INDEX_SCAN_BATCH_SIZE);
247     setIfMissing(TIKV_INDEX_SCAN_CONCURRENCY, DEF_INDEX_SCAN_CONCURRENCY);
248     setIfMissing(TIKV_TABLE_SCAN_CONCURRENCY, DEF_TABLE_SCAN_CONCURRENCY);
249     setIfMissing(TIKV_BATCH_GET_CONCURRENCY, DEF_BATCH_GET_CONCURRENCY);
250     setIfMissing(TIKV_BATCH_PUT_CONCURRENCY, DEF_BATCH_PUT_CONCURRENCY);
251     setIfMissing(TIKV_BATCH_DELETE_CONCURRENCY, DEF_BATCH_DELETE_CONCURRENCY);
252     setIfMissing(TIKV_BATCH_SCAN_CONCURRENCY, DEF_BATCH_SCAN_CONCURRENCY);
253     setIfMissing(TIKV_DELETE_RANGE_CONCURRENCY, DEF_DELETE_RANGE_CONCURRENCY);
254     setIfMissing(TIKV_REQUEST_COMMAND_PRIORITY, LOW_COMMAND_PRIORITY);
255     setIfMissing(TIKV_REQUEST_ISOLATION_LEVEL, SNAPSHOT_ISOLATION_LEVEL);
256     setIfMissing(TIKV_REQUEST_ISOLATION_LEVEL, SNAPSHOT_ISOLATION_LEVEL);
257     setIfMissing(TIKV_SHOW_ROWID, DEF_SHOW_ROWID);
258     setIfMissing(TIKV_DB_PREFIX, DEF_DB_PREFIX);
259     setIfMissing(TIKV_DB_PREFIX, DEF_DB_PREFIX);
260     setIfMissing(TIKV_KV_CLIENT_CONCURRENCY, DEF_KV_CLIENT_CONCURRENCY);
261     setIfMissing(TIKV_KV_MODE, TXN_KV_MODE);
262     setIfMissing(TIKV_REPLICA_READ, DEF_REPLICA_READ);
263     setIfMissing(TIKV_METRICS_ENABLE, DEF_METRICS_ENABLE);
264     setIfMissing(TIKV_METRICS_PORT, DEF_METRICS_PORT);
265     setIfMissing(TIKV_NETWORK_MAPPING_NAME, DEF_TIKV_NETWORK_MAPPING_NAME);
266     setIfMissing(TIKV_ENABLE_GRPC_FORWARD, DEF_GRPC_FORWARD_ENABLE);
267     setIfMissing(TIKV_GRPC_HEALTH_CHECK_TIMEOUT, DEF_CHECK_HEALTH_TIMEOUT);
268     setIfMissing(TIKV_HEALTH_CHECK_PERIOD_DURATION, DEF_HEALTH_CHECK_PERIOD_DURATION);
269     setIfMissing(TIKV_ENABLE_ATOMIC_FOR_CAS, DEF_TIKV_ENABLE_ATOMIC_FOR_CAS);
270     setIfMissing(TIKV_IMPORTER_MAX_KV_BATCH_BYTES, DEF_TIKV_IMPORTER_MAX_KV_BATCH_BYTES);
271     setIfMissing(TIKV_IMPORTER_MAX_KV_BATCH_SIZE, DEF_TIKV_IMPORTER_MAX_KV_BATCH_SIZE);
272     setIfMissing(TIKV_SCATTER_WAIT_SECONDS, DEF_TIKV_SCATTER_WAIT_SECONDS);
273     setIfMissing(TIKV_RAWKV_DEFAULT_BACKOFF_IN_MS, DEF_TIKV_RAWKV_DEFAULT_BACKOFF_IN_MS);
274     setIfMissing(TIKV_GRPC_KEEPALIVE_TIME, DEF_TIKV_GRPC_KEEPALIVE_TIME);
275     setIfMissing(TIKV_GRPC_KEEPALIVE_TIMEOUT, DEF_TIKV_GRPC_KEEPALIVE_TIMEOUT);
276     setIfMissing(TIKV_GRPC_IDLE_TIMEOUT, DEF_TIKV_GRPC_IDLE_TIMEOUT);
277     setIfMissing(TIKV_TLS_ENABLE, DEF_TIKV_TLS_ENABLE);
278     setIfMissing(TIKV_USE_JKS, DEF_TIKV_USE_JKS);
279     setIfMissing(TIFLASH_ENABLE, DEF_TIFLASH_ENABLE);
280     setIfMissing(TIKV_WARM_UP_ENABLE, DEF_TIKV_WARM_UP_ENABLE);
281     setIfMissing(TIKV_RAWKV_READ_TIMEOUT_IN_MS, DEF_TIKV_RAWKV_READ_TIMEOUT_IN_MS);
282     setIfMissing(TIKV_RAWKV_WRITE_TIMEOUT_IN_MS, DEF_TIKV_RAWKV_WRITE_TIMEOUT_IN_MS);
283     setIfMissing(TIKV_RAWKV_BATCH_READ_TIMEOUT_IN_MS, DEF_TIKV_RAWKV_BATCH_READ_TIMEOUT_IN_MS);
284     setIfMissing(TIKV_RAWKV_BATCH_WRITE_TIMEOUT_IN_MS, DEF_TIKV_RAWKV_BATCH_WRITE_TIMEOUT_IN_MS);
285     setIfMissing(TIKV_RAWKV_SCAN_TIMEOUT_IN_MS, DEF_TIKV_RAWKV_SCAN_TIMEOUT_IN_MS);
286     setIfMissing(TIKV_RAWKV_CLEAN_TIMEOUT_IN_MS, DEF_TIKV_RAWKV_CLEAN_TIMEOUT_IN_MS);
287     setIfMissing(TIKV_BO_REGION_MISS_BASE_IN_MS, DEF_TIKV_BO_REGION_MISS_BASE_IN_MS);
288     setIfMissing(TIKV_RAWKV_SCAN_SLOWLOG_IN_MS, DEF_TIKV_RAWKV_SCAN_SLOWLOG_IN_MS);
289     setIfMissing(TiKV_CIRCUIT_BREAK_ENABLE, DEF_TiKV_CIRCUIT_BREAK_ENABLE);
290     setIfMissing(
291         TiKV_CIRCUIT_BREAK_AVAILABILITY_WINDOW_IN_SECONDS,
292         DEF_TiKV_CIRCUIT_BREAK_AVAILABILITY_WINDOW_IN_SECONDS);
293     setIfMissing(
294         TiKV_CIRCUIT_BREAK_AVAILABILITY_ERROR_THRESHOLD_PERCENTAGE,
295         DEF_TiKV_CIRCUIT_BREAK_AVAILABILITY_ERROR_THRESHOLD_PERCENTAGE);
296     setIfMissing(
297         TiKV_CIRCUIT_BREAK_AVAILABILITY_REQUEST_VOLUMN_THRESHOLD,
298         DEF_TiKV_CIRCUIT_BREAK_AVAILABILITY_REQUST_VOLUMN_THRESHOLD);
299     setIfMissing(
300         TiKV_CIRCUIT_BREAK_SLEEP_WINDOW_IN_SECONDS, DEF_TiKV_CIRCUIT_BREAK_SLEEP_WINDOW_IN_SECONDS);
301     setIfMissing(
302         TiKV_CIRCUIT_BREAK_ATTEMPT_REQUEST_COUNT, DEF_TiKV_CIRCUIT_BREAK_ATTEMPT_REQUEST_COUNT);
303     setIfMissing(TIKV_SCAN_REGIONS_LIMIT, DEF_TIKV_SCAN_REGIONS_LIMIT);
304 
305     setIfMissing(TIKV_API_VERSION, DEF_TIKV_API_VERSION);
306   }
307 
308   public static void listAll() {
309     logger.info("static configurations are:" + new ArrayList<>(settings.entrySet()));
310   }
311 
312   private static void set(String key, String value) {
313     if (key == null) {
314       throw new NullPointerException("null key");
315     }
316     if (value == null) {
317       throw new NullPointerException("null value for " + key);
318     }
319     settings.put(key, value);
320   }
321 
322   private static void setIfMissing(String key, int value) {
323     setIfMissing(key, String.valueOf(value));
324   }
325 
326   private static void setIfMissing(String key, boolean value) {
327     setIfMissing(key, String.valueOf(value));
328   }
329 
330   private static void setIfMissing(String key, String value) {
331     if (key == null) {
332       throw new NullPointerException("null key");
333     }
334     if (value == null) {
335       throw new NullPointerException("null value for " + key);
336     }
337     settings.putIfAbsent(key, value);
338   }
339 
340   private static Optional<String> getOption(String key) {
341     return Optional.ofNullable(settings.get(key));
342   }
343 
344   private static String get(String key) {
345     Optional<String> option = getOption(key);
346     if (!option.isPresent()) {
347       throw new NoSuchElementException(key);
348     }
349     return option.get();
350   }
351 
352   public static int getInt(String key) {
353     return Integer.parseInt(get(key));
354   }
355 
356   public static Optional<Integer> getIntOption(String key) {
357     return getOption(key).map(Integer::parseInt);
358   }
359 
360   private static int getInt(String key, int defaultValue) {
361     try {
362       return getOption(key).map(Integer::parseInt).orElse(defaultValue);
363     } catch (NumberFormatException e) {
364       return defaultValue;
365     }
366   }
367 
368   private static long getLong(String key) {
369     return Long.parseLong(get(key));
370   }
371 
372   private static long getLong(String key, long defaultValue) {
373     try {
374       return getOption(key).map(Long::parseLong).orElse(defaultValue);
375     } catch (NumberFormatException e) {
376       return defaultValue;
377     }
378   }
379 
380   private static double getDouble(String key) {
381     return Double.parseDouble(get(key));
382   }
383 
384   private static double getDouble(String key, double defaultValue) {
385     try {
386       return getOption(key).map(Double::parseDouble).orElse(defaultValue);
387     } catch (NumberFormatException e) {
388       return defaultValue;
389     }
390   }
391 
392   private static boolean getBoolean(String key) {
393     return Boolean.parseBoolean(get(key));
394   }
395 
396   private static boolean getBoolean(String key, boolean defaultValue) {
397     try {
398       return getOption(key).map(Boolean::parseBoolean).orElse(defaultValue);
399     } catch (NumberFormatException e) {
400       return defaultValue;
401     }
402   }
403 
404   private static Long getTimeAsMs(String key) {
405     return Utils.timeStringAsMs(get(key));
406   }
407 
408   private static Long getTimeAsSeconds(String key) {
409     return Utils.timeStringAsSec(get(key));
410   }
411 
412   private static List<URI> getPdAddrs(String key) {
413     Optional<String> pdAddrs = getOption(key);
414     if (pdAddrs.isPresent()) {
415       return strToURI(pdAddrs.get());
416     } else {
417       return new ArrayList<>();
418     }
419   }
420 
421   private static CommandPri getCommandPri(String key) {
422     String priority = get(key).toUpperCase(Locale.ROOT);
423     switch (priority) {
424       case NORMAL_COMMAND_PRIORITY:
425         return CommandPri.Normal;
426       case LOW_COMMAND_PRIORITY:
427         return CommandPri.Low;
428       case HIGH_COMMAND_PRIORITY:
429         return CommandPri.High;
430       default:
431         return CommandPri.UNRECOGNIZED;
432     }
433   }
434 
435   private static IsolationLevel getIsolationLevel(String key) {
436     String isolationLevel = get(key).toUpperCase(Locale.ROOT);
437     switch (isolationLevel) {
438       case READ_COMMITTED_ISOLATION_LEVEL:
439         return IsolationLevel.RC;
440       case SNAPSHOT_ISOLATION_LEVEL:
441         return IsolationLevel.SI;
442       default:
443         return IsolationLevel.UNRECOGNIZED;
444     }
445   }
446 
447   private static KVMode getKvMode(String key) {
448     if (get(key).toUpperCase(Locale.ROOT).equals(RAW_KV_MODE)) {
449       return KVMode.RAW;
450     } else {
451       return KVMode.TXN;
452     }
453   }
454 
455   private static ReplicaRead getReplicaRead(String key) {
456     String value = get(key).toUpperCase(Locale.ROOT);
457     if (FOLLOWER.equals(value)) {
458       return ReplicaRead.FOLLOWER;
459     } else if (LEADER_AND_FOLLOWER.equals(value)) {
460       return ReplicaRead.LEADER_AND_FOLLOWER;
461     } else {
462       return ReplicaRead.LEADER;
463     }
464   }
465 
466   private long timeout = getTimeAsMs(TIKV_GRPC_TIMEOUT);
467   private long ingestTimeout = getTimeAsMs(TIKV_GRPC_INGEST_TIMEOUT);
468   private long forwardTimeout = getTimeAsMs(TIKV_GRPC_FORWARD_TIMEOUT);
469   private long warmUpTimeout = getTimeAsMs(TIKV_GRPC_WARM_UP_TIMEOUT);
470   private long pdFirstGetMemberTimeout = getTimeAsMs(TIKV_PD_FIRST_GET_MEMBER_TIMEOUT);
471   private long scanTimeout = getTimeAsMs(TIKV_GRPC_SCAN_TIMEOUT);
472   private int maxFrameSize = getInt(TIKV_GRPC_MAX_FRAME_SIZE);
473   private long connRecycleTime = getTimeAsSeconds(TIKV_CONN_RECYCLE_TIME);
474   private List<URI> pdAddrs = getPdAddrs(TIKV_PD_ADDRESSES);
475   private int indexScanBatchSize = getInt(TIKV_INDEX_SCAN_BATCH_SIZE);
476   private int indexScanConcurrency = getInt(TIKV_INDEX_SCAN_CONCURRENCY);
477   private int tableScanConcurrency = getInt(TIKV_TABLE_SCAN_CONCURRENCY);
478   private int batchGetConcurrency = getInt(TIKV_BATCH_GET_CONCURRENCY);
479   private int batchPutConcurrency = getInt(TIKV_BATCH_PUT_CONCURRENCY);
480   private int batchDeleteConcurrency = getInt(TIKV_BATCH_DELETE_CONCURRENCY);
481   private int batchScanConcurrency = getInt(TIKV_BATCH_SCAN_CONCURRENCY);
482   private int deleteRangeConcurrency = getInt(TIKV_DELETE_RANGE_CONCURRENCY);
483   private CommandPri commandPriority = getCommandPri(TIKV_REQUEST_COMMAND_PRIORITY);
484   private IsolationLevel isolationLevel = getIsolationLevel(TIKV_REQUEST_ISOLATION_LEVEL);
485   private boolean showRowId = getBoolean(TIKV_SHOW_ROWID);
486   private String dbPrefix = get(TIKV_DB_PREFIX);
487   private KVMode kvMode = getKvMode(TIKV_KV_MODE);
488   private boolean enableGrpcForward = getBoolean(TIKV_ENABLE_GRPC_FORWARD);
489 
490   private int kvClientConcurrency = getInt(TIKV_KV_CLIENT_CONCURRENCY);
491   private ReplicaRead replicaRead = getReplicaRead(TIKV_REPLICA_READ);
492   private ReplicaSelector internalReplicaSelector = getReplicaSelector(replicaRead);
493   private ReplicaSelector replicaSelector;
494 
495   private boolean metricsEnable = getBoolean(TIKV_METRICS_ENABLE);
496   private int metricsPort = getInt(TIKV_METRICS_PORT);
497   private int grpcHealthCheckTimeout = getInt(TIKV_GRPC_HEALTH_CHECK_TIMEOUT);
498   private int healthCheckPeriodDuration = getInt(TIKV_HEALTH_CHECK_PERIOD_DURATION);
499 
500   private final String networkMappingName = get(TIKV_NETWORK_MAPPING_NAME);
501   private HostMapping hostMapping = null;
502 
503   private boolean enableAtomicForCAS = getBoolean(TIKV_ENABLE_ATOMIC_FOR_CAS);
504 
505   private int importerMaxKVBatchBytes = getInt(TIKV_IMPORTER_MAX_KV_BATCH_BYTES);
506 
507   private int importerMaxKVBatchSize = getInt(TIKV_IMPORTER_MAX_KV_BATCH_SIZE);
508 
509   private int scatterWaitSeconds = getInt(TIKV_SCATTER_WAIT_SECONDS);
510 
511   private int rawKVDefaultBackoffInMS = getInt(TIKV_RAWKV_DEFAULT_BACKOFF_IN_MS);
512   private int rawKVReadTimeoutInMS = getInt(TIKV_RAWKV_READ_TIMEOUT_IN_MS);
513   private int rawKVWriteTimeoutInMS = getInt(TIKV_RAWKV_WRITE_TIMEOUT_IN_MS);
514   private int rawKVBatchReadTimeoutInMS = getInt(TIKV_RAWKV_BATCH_READ_TIMEOUT_IN_MS);
515   private int rawKVBatchWriteTimeoutInMS = getInt(TIKV_RAWKV_BATCH_WRITE_TIMEOUT_IN_MS);
516   private int rawKVScanTimeoutInMS = getInt(TIKV_RAWKV_SCAN_TIMEOUT_IN_MS);
517   private int rawKVCleanTimeoutInMS = getInt(TIKV_RAWKV_CLEAN_TIMEOUT_IN_MS);
518   private Integer rawKVReadSlowLogInMS = getIntOption(TIKV_RAWKV_READ_SLOWLOG_IN_MS).orElse(null);
519   private Integer rawKVWriteSlowLogInMS = getIntOption(TIKV_RAWKV_WRITE_SLOWLOG_IN_MS).orElse(null);
520   private Integer rawKVBatchReadSlowLogInMS =
521       getIntOption(TIKV_RAWKV_BATCH_READ_SLOWLOG_IN_MS).orElse(null);
522   private Integer rawKVBatchWriteSlowLogInMS =
523       getIntOption(TIKV_RAWKV_BATCH_WRITE_SLOWLOG_IN_MS).orElse(null);
524   private int rawKVScanSlowLogInMS = getInt(TIKV_RAWKV_SCAN_SLOWLOG_IN_MS);
525   private double rawKVServerSlowLogFactor = getDouble(TIKV_RAWKV_SERVER_SLOWLOG_FACTOR, 0.5);
526 
527   private boolean tlsEnable = getBoolean(TIKV_TLS_ENABLE);
528   private long certReloadInterval = getTimeAsSeconds(TIKV_TLS_RELOAD_INTERVAL);
529 
530   private String trustCertCollectionFile = getOption(TIKV_TRUST_CERT_COLLECTION).orElse(null);
531   private String keyCertChainFile = getOption(TIKV_KEY_CERT_CHAIN).orElse(null);
532   private String keyFile = getOption(TIKV_KEY_FILE).orElse(null);
533 
534   private boolean useJks = getBoolean(TIKV_USE_JKS);
535   private String jksKeyPath = getOption(TIKV_JKS_KEY_PATH).orElse(null);
536   private String jksKeyPassword = getOption(TIKV_JKS_KEY_PASSWORD).orElse(null);
537   private String jksTrustPath = getOption(TIKV_JKS_TRUST_PATH).orElse(null);
538   private String jksTrustPassword = getOption(TIKV_JKS_TRUST_PASSWORD).orElse(null);
539 
540   private final boolean tiFlashEnable = getBoolean(TIFLASH_ENABLE);
541   private boolean warmUpEnable = getBoolean(TIKV_WARM_UP_ENABLE);
542 
543   private boolean isTest = false;
544 
545   private int keepaliveTime = getInt(TIKV_GRPC_KEEPALIVE_TIME);
546   private int keepaliveTimeout = getInt(TIKV_GRPC_KEEPALIVE_TIMEOUT);
547   private int idleTimeout = getInt(TIKV_GRPC_IDLE_TIMEOUT);
548 
549   private boolean circuitBreakEnable = getBoolean(TiKV_CIRCUIT_BREAK_ENABLE);
550   private int circuitBreakAvailabilityWindowInSeconds =
551       getInt(TiKV_CIRCUIT_BREAK_AVAILABILITY_WINDOW_IN_SECONDS);
552   private int circuitBreakAvailabilityErrorThresholdPercentage =
553       getInt(TiKV_CIRCUIT_BREAK_AVAILABILITY_ERROR_THRESHOLD_PERCENTAGE);
554   private int circuitBreakAvailabilityRequestVolumnThreshold =
555       getInt(TiKV_CIRCUIT_BREAK_AVAILABILITY_REQUEST_VOLUMN_THRESHOLD);
556   private int circuitBreakSleepWindowInSeconds = getInt(TiKV_CIRCUIT_BREAK_SLEEP_WINDOW_IN_SECONDS);
557   private int circuitBreakAttemptRequestCount = getInt(TiKV_CIRCUIT_BREAK_ATTEMPT_REQUEST_COUNT);
558 
559   private int scanRegionsLimit = getInt(TIKV_SCAN_REGIONS_LIMIT);
560 
561   private ApiVersion apiVersion = ApiVersion.fromInt(getInt(TIKV_API_VERSION));
562 
563   public enum KVMode {
564     TXN,
565     RAW
566   }
567 
568   public enum ReplicaRead {
569     LEADER,
570     FOLLOWER,
571     LEADER_AND_FOLLOWER
572   }
573 
574   public TiConfiguration() {
575     if (rawKVServerSlowLogFactor < 0 || rawKVServerSlowLogFactor > 1) {
576       throw new IllegalArgumentException("rawkv_server_slowlog_factor must be in range [0, 1]");
577     }
578   }
579 
580   public static TiConfiguration createDefault() {
581     return new TiConfiguration();
582   }
583 
584   public static TiConfiguration createDefault(String pdAddrsStr) {
585     Objects.requireNonNull(pdAddrsStr, "pdAddrsStr is null");
586     TiConfiguration conf = new TiConfiguration();
587     conf.pdAddrs = strToURI(pdAddrsStr);
588     return conf;
589   }
590 
591   public static TiConfiguration createRawDefault() {
592     TiConfiguration conf = new TiConfiguration();
593     conf.kvMode = KVMode.RAW;
594     return conf;
595   }
596 
597   public static TiConfiguration createRawDefault(String pdAddrsStr) {
598     Objects.requireNonNull(pdAddrsStr, "pdAddrsStr is null");
599     TiConfiguration conf = new TiConfiguration();
600     conf.pdAddrs = strToURI(pdAddrsStr);
601     conf.kvMode = KVMode.RAW;
602     return conf;
603   }
604 
605   private static List<URI> strToURI(String addressStr) {
606     Objects.requireNonNull(addressStr);
607     String[] addrs = addressStr.split(",");
608     Arrays.sort(addrs);
609     return PDUtils.addrsToUrls(addrs);
610   }
611 
612   public static <E> String listToString(List<E> list) {
613     StringBuilder sb = new StringBuilder();
614     sb.append("[");
615     for (int i = 0; i < list.size(); i++) {
616       sb.append(list.get(i).toString());
617       if (i != list.size() - 1) {
618         sb.append(",");
619       }
620     }
621     sb.append("]");
622     return sb.toString();
623   }
624 
625   public long getTimeout() {
626     return timeout;
627   }
628 
629   public TiConfiguration setTimeout(long timeout) {
630     this.timeout = timeout;
631     return this;
632   }
633 
634   public long getIngestTimeout() {
635     return ingestTimeout;
636   }
637 
638   public void setIngestTimeout(long ingestTimeout) {
639     this.ingestTimeout = ingestTimeout;
640   }
641 
642   public long getForwardTimeout() {
643     return forwardTimeout;
644   }
645 
646   public TiConfiguration setForwardTimeout(long timeout) {
647     this.forwardTimeout = timeout;
648     return this;
649   }
650 
651   public long getWarmUpTimeout() {
652     return warmUpTimeout;
653   }
654 
655   public TiConfiguration setWarmUpTimeout(long timeout) {
656     this.warmUpTimeout = timeout;
657     return this;
658   }
659 
660   public long getPdFirstGetMemberTimeout() {
661     return pdFirstGetMemberTimeout;
662   }
663 
664   public void setPdFirstGetMemberTimeout(long pdFirstGetMemberTimeout) {
665     this.pdFirstGetMemberTimeout = pdFirstGetMemberTimeout;
666   }
667 
668   public long getScanTimeout() {
669     return scanTimeout;
670   }
671 
672   public TiConfiguration setScanTimeout(long scanTimeout) {
673     this.scanTimeout = scanTimeout;
674     return this;
675   }
676 
677   public List<URI> getPdAddrs() {
678     return pdAddrs;
679   }
680 
681   public String getPdAddrsString() {
682     return listToString(pdAddrs);
683   }
684 
685   public int getScanBatchSize() {
686     return DEF_SCAN_BATCH_SIZE;
687   }
688 
689   public int getMaxFrameSize() {
690     return maxFrameSize;
691   }
692 
693   public TiConfiguration setMaxFrameSize(int maxFrameSize) {
694     this.maxFrameSize = maxFrameSize;
695     return this;
696   }
697 
698   public long getConnRecycleTimeInSeconds() {
699     return connRecycleTime;
700   }
701 
702   public TiConfiguration setConnRecycleTimeInSeconds(int connRecycleTime) {
703     this.connRecycleTime = connRecycleTime;
704     return this;
705   }
706 
707   public int getIndexScanBatchSize() {
708     return indexScanBatchSize;
709   }
710 
711   public TiConfiguration setIndexScanBatchSize(int indexScanBatchSize) {
712     this.indexScanBatchSize = indexScanBatchSize;
713     return this;
714   }
715 
716   public int getIndexScanConcurrency() {
717     return indexScanConcurrency;
718   }
719 
720   public TiConfiguration setIndexScanConcurrency(int indexScanConcurrency) {
721     this.indexScanConcurrency = indexScanConcurrency;
722     return this;
723   }
724 
725   public int getTableScanConcurrency() {
726     return tableScanConcurrency;
727   }
728 
729   public TiConfiguration setTableScanConcurrency(int tableScanConcurrency) {
730     this.tableScanConcurrency = tableScanConcurrency;
731     return this;
732   }
733 
734   public int getBatchGetConcurrency() {
735     return batchGetConcurrency;
736   }
737 
738   public TiConfiguration setBatchGetConcurrency(int batchGetConcurrency) {
739     this.batchGetConcurrency = batchGetConcurrency;
740     return this;
741   }
742 
743   public int getBatchPutConcurrency() {
744     return batchPutConcurrency;
745   }
746 
747   public TiConfiguration setBatchPutConcurrency(int batchPutConcurrency) {
748     this.batchPutConcurrency = batchPutConcurrency;
749     return this;
750   }
751 
752   public int getBatchDeleteConcurrency() {
753     return batchDeleteConcurrency;
754   }
755 
756   public TiConfiguration setBatchDeleteConcurrency(int batchDeleteConcurrency) {
757     this.batchDeleteConcurrency = batchDeleteConcurrency;
758     return this;
759   }
760 
761   public int getBatchScanConcurrency() {
762     return batchScanConcurrency;
763   }
764 
765   public TiConfiguration setBatchScanConcurrency(int batchScanConcurrency) {
766     this.batchScanConcurrency = batchScanConcurrency;
767     return this;
768   }
769 
770   public int getDeleteRangeConcurrency() {
771     return deleteRangeConcurrency;
772   }
773 
774   public TiConfiguration setDeleteRangeConcurrency(int deleteRangeConcurrency) {
775     this.deleteRangeConcurrency = deleteRangeConcurrency;
776     return this;
777   }
778 
779   public CommandPri getCommandPriority() {
780     return commandPriority;
781   }
782 
783   public TiConfiguration setCommandPriority(CommandPri commandPriority) {
784     this.commandPriority = commandPriority;
785     return this;
786   }
787 
788   public IsolationLevel getIsolationLevel() {
789     return isolationLevel;
790   }
791 
792   public TiConfiguration setIsolationLevel(IsolationLevel isolationLevel) {
793     this.isolationLevel = isolationLevel;
794     return this;
795   }
796 
797   public boolean ifShowRowId() {
798     return showRowId;
799   }
800 
801   public TiConfiguration setShowRowId(boolean flag) {
802     this.showRowId = flag;
803     return this;
804   }
805 
806   public String getDBPrefix() {
807     return dbPrefix;
808   }
809 
810   public TiConfiguration setDBPrefix(String dbPrefix) {
811     this.dbPrefix = dbPrefix;
812     return this;
813   }
814 
815   public KVMode getKvMode() {
816     return kvMode;
817   }
818 
819   public boolean isRawKVMode() {
820     return getKvMode() == TiConfiguration.KVMode.RAW;
821   }
822 
823   public boolean isTxnKVMode() {
824     return getKvMode() == KVMode.TXN;
825   }
826 
827   public TiConfiguration setKvMode(String kvMode) {
828     this.kvMode = KVMode.valueOf(kvMode);
829     return this;
830   }
831 
832   public int getKvClientConcurrency() {
833     return kvClientConcurrency;
834   }
835 
836   public TiConfiguration setKvClientConcurrency(int kvClientConcurrency) {
837     this.kvClientConcurrency = kvClientConcurrency;
838     return this;
839   }
840 
841   public ReplicaRead getReplicaRead() {
842     return replicaRead;
843   }
844 
845   public TiConfiguration setReplicaRead(ReplicaRead replicaRead) {
846     this.replicaRead = replicaRead;
847     this.internalReplicaSelector = getReplicaSelector(this.replicaRead);
848     return this;
849   }
850 
851   private ReplicaSelector getReplicaSelector(ReplicaRead replicaRead) {
852     if (TiConfiguration.ReplicaRead.LEADER.equals(replicaRead)) {
853       return ReplicaSelector.LEADER;
854     } else if (TiConfiguration.ReplicaRead.FOLLOWER.equals(replicaRead)) {
855       return ReplicaSelector.FOLLOWER;
856     } else if (TiConfiguration.ReplicaRead.LEADER_AND_FOLLOWER.equals(replicaRead)) {
857       return ReplicaSelector.LEADER_AND_FOLLOWER;
858     } else {
859       return null;
860     }
861   }
862 
863   public ReplicaSelector getReplicaSelector() {
864     if (replicaSelector != null) {
865       return replicaSelector;
866     } else {
867       return internalReplicaSelector;
868     }
869   }
870 
871   public void setReplicaSelector(ReplicaSelector replicaSelector) {
872     this.replicaSelector = replicaSelector;
873   }
874 
875   public boolean isMetricsEnable() {
876     return metricsEnable;
877   }
878 
879   public TiConfiguration setMetricsEnable(boolean metricsEnable) {
880     this.metricsEnable = metricsEnable;
881     return this;
882   }
883 
884   public int getMetricsPort() {
885     return metricsPort;
886   }
887 
888   public TiConfiguration setMetricsPort(int metricsPort) {
889     this.metricsPort = metricsPort;
890     return this;
891   }
892 
893   public String getNetworkMappingName() {
894     return this.networkMappingName;
895   }
896 
897   public HostMapping getHostMapping() {
898     return hostMapping;
899   }
900 
901   public void setHostMapping(HostMapping mapping) {
902     this.hostMapping = mapping;
903   }
904 
905   public boolean getEnableGrpcForward() {
906     return this.enableGrpcForward;
907   }
908 
909   public void setEnableGrpcForward(boolean enableGrpcForward) {
910     this.enableGrpcForward = enableGrpcForward;
911   }
912 
913   public long getGrpcHealthCheckTimeout() {
914     return this.grpcHealthCheckTimeout;
915   }
916 
917   public void setGrpcHealthCheckTimeout(int grpcHealthCheckTimeout) {
918     this.grpcHealthCheckTimeout = grpcHealthCheckTimeout;
919   }
920 
921   public long getHealthCheckPeriodDuration() {
922     return this.healthCheckPeriodDuration;
923   }
924 
925   public void setHealthCheckPeriodDuration(int healthCheckPeriodDuration) {
926     this.healthCheckPeriodDuration = healthCheckPeriodDuration;
927   }
928 
929   public boolean isEnableAtomicForCAS() {
930     return enableAtomicForCAS;
931   }
932 
933   public void setEnableAtomicForCAS(boolean enableAtomicForCAS) {
934     this.enableAtomicForCAS = enableAtomicForCAS;
935   }
936 
937   public int getImporterMaxKVBatchBytes() {
938     return importerMaxKVBatchBytes;
939   }
940 
941   public void setImporterMaxKVBatchBytes(int importerMaxKVBatchBytes) {
942     this.importerMaxKVBatchBytes = importerMaxKVBatchBytes;
943   }
944 
945   public int getImporterMaxKVBatchSize() {
946     return importerMaxKVBatchSize;
947   }
948 
949   public void setImporterMaxKVBatchSize(int importerMaxKVBatchSize) {
950     this.importerMaxKVBatchSize = importerMaxKVBatchSize;
951   }
952 
953   public int getScatterWaitSeconds() {
954     return scatterWaitSeconds;
955   }
956 
957   public void setScatterWaitSeconds(int scatterWaitSeconds) {
958     this.scatterWaitSeconds = scatterWaitSeconds;
959   }
960 
961   public int getRawKVDefaultBackoffInMS() {
962     return rawKVDefaultBackoffInMS;
963   }
964 
965   public void setRawKVDefaultBackoffInMS(int rawKVDefaultBackoffInMS) {
966     this.rawKVDefaultBackoffInMS = rawKVDefaultBackoffInMS;
967   }
968 
969   public boolean isTest() {
970     return isTest;
971   }
972 
973   public void setTest(boolean test) {
974     isTest = test;
975   }
976 
977   public int getKeepaliveTime() {
978     return keepaliveTime;
979   }
980 
981   public void setKeepaliveTime(int keepaliveTime) {
982     this.keepaliveTime = keepaliveTime;
983   }
984 
985   public int getKeepaliveTimeout() {
986     return keepaliveTimeout;
987   }
988 
989   public void setKeepaliveTimeout(int timeout) {
990     this.keepaliveTimeout = timeout;
991   }
992 
993   public int getIdleTimeout() {
994     return idleTimeout;
995   }
996 
997   public void setIdleTimeout(int timeout) {
998     this.idleTimeout = timeout;
999   }
1000 
1001   public boolean isTiFlashEnabled() {
1002     return tiFlashEnable;
1003   }
1004 
1005   public boolean isWarmUpEnable() {
1006     return warmUpEnable;
1007   }
1008 
1009   public void setWarmUpEnable(boolean warmUpEnable) {
1010     this.warmUpEnable = warmUpEnable;
1011   }
1012 
1013   public boolean isTlsEnable() {
1014     return tlsEnable;
1015   }
1016 
1017   public long getCertReloadIntervalInSeconds() {
1018     return certReloadInterval;
1019   }
1020 
1021   public TiConfiguration setCertReloadIntervalInSeconds(long interval) {
1022     this.certReloadInterval = interval;
1023     return this;
1024   }
1025 
1026   public void setTlsEnable(boolean tlsEnable) {
1027     this.tlsEnable = tlsEnable;
1028   }
1029 
1030   public String getTrustCertCollectionFile() {
1031     return trustCertCollectionFile;
1032   }
1033 
1034   public void setTrustCertCollectionFile(String trustCertCollectionFile) {
1035     this.trustCertCollectionFile = trustCertCollectionFile;
1036   }
1037 
1038   public String getKeyCertChainFile() {
1039     return keyCertChainFile;
1040   }
1041 
1042   public void setKeyCertChainFile(String keyCertChainFile) {
1043     this.keyCertChainFile = keyCertChainFile;
1044   }
1045 
1046   public String getKeyFile() {
1047     return keyFile;
1048   }
1049 
1050   public void setKeyFile(String keyFile) {
1051     this.keyFile = keyFile;
1052   }
1053 
1054   public boolean isJksEnable() {
1055     return useJks;
1056   }
1057 
1058   public void setJksEnable(boolean useJks) {
1059     this.useJks = useJks;
1060   }
1061 
1062   public String getJksKeyPath() {
1063     return jksKeyPath;
1064   }
1065 
1066   public void setJksKeyPath(String jksKeyPath) {
1067     this.jksKeyPath = jksKeyPath;
1068   }
1069 
1070   public String getJksKeyPassword() {
1071     return jksKeyPassword;
1072   }
1073 
1074   public void setJksKeyPassword(String jksKeyPassword) {
1075     this.jksKeyPassword = jksKeyPassword;
1076   }
1077 
1078   public String getJksTrustPath() {
1079     return jksTrustPath;
1080   }
1081 
1082   public void setJksTrustPath(String jksTrustPath) {
1083     this.jksTrustPath = jksTrustPath;
1084   }
1085 
1086   public String getJksTrustPassword() {
1087     return jksTrustPassword;
1088   }
1089 
1090   public void setJksTrustPassword(String jksTrustPassword) {
1091     this.jksTrustPassword = jksTrustPassword;
1092   }
1093 
1094   public int getRawKVReadTimeoutInMS() {
1095     return rawKVReadTimeoutInMS;
1096   }
1097 
1098   public void setRawKVReadTimeoutInMS(int rawKVReadTimeoutInMS) {
1099     this.rawKVReadTimeoutInMS = rawKVReadTimeoutInMS;
1100   }
1101 
1102   public int getRawKVWriteTimeoutInMS() {
1103     return rawKVWriteTimeoutInMS;
1104   }
1105 
1106   public void setRawKVWriteTimeoutInMS(int rawKVWriteTimeoutInMS) {
1107     this.rawKVWriteTimeoutInMS = rawKVWriteTimeoutInMS;
1108   }
1109 
1110   public int getRawKVBatchReadTimeoutInMS() {
1111     return rawKVBatchReadTimeoutInMS;
1112   }
1113 
1114   public void setRawKVBatchReadTimeoutInMS(int rawKVBatchReadTimeoutInMS) {
1115     this.rawKVBatchReadTimeoutInMS = rawKVBatchReadTimeoutInMS;
1116   }
1117 
1118   public int getRawKVBatchWriteTimeoutInMS() {
1119     return rawKVBatchWriteTimeoutInMS;
1120   }
1121 
1122   public void setRawKVBatchWriteTimeoutInMS(int rawKVBatchWriteTimeoutInMS) {
1123     this.rawKVBatchWriteTimeoutInMS = rawKVBatchWriteTimeoutInMS;
1124   }
1125 
1126   public int getRawKVScanTimeoutInMS() {
1127     return rawKVScanTimeoutInMS;
1128   }
1129 
1130   public void setRawKVScanTimeoutInMS(int rawKVScanTimeoutInMS) {
1131     this.rawKVScanTimeoutInMS = rawKVScanTimeoutInMS;
1132   }
1133 
1134   public int getRawKVCleanTimeoutInMS() {
1135     return rawKVCleanTimeoutInMS;
1136   }
1137 
1138   public void setRawKVCleanTimeoutInMS(int rawKVCleanTimeoutInMS) {
1139     this.rawKVCleanTimeoutInMS = rawKVCleanTimeoutInMS;
1140   }
1141 
1142   public Integer getRawKVReadSlowLogInMS() {
1143     return Optional.ofNullable(rawKVReadSlowLogInMS).orElse((int) (getTimeout() * 2));
1144   }
1145 
1146   public void setRawKVReadSlowLogInMS(Integer rawKVReadSlowLogInMS) {
1147     this.rawKVReadSlowLogInMS = rawKVReadSlowLogInMS;
1148   }
1149 
1150   public Integer getRawKVWriteSlowLogInMS() {
1151     return Optional.ofNullable(rawKVWriteSlowLogInMS).orElse((int) (getTimeout() * 2));
1152   }
1153 
1154   public void setRawKVWriteSlowLogInMS(Integer rawKVWriteSlowLogInMS) {
1155     this.rawKVWriteSlowLogInMS = rawKVWriteSlowLogInMS;
1156   }
1157 
1158   public Integer getRawKVBatchReadSlowLogInMS() {
1159     return Optional.ofNullable(rawKVBatchReadSlowLogInMS).orElse((int) (getTimeout() * 2));
1160   }
1161 
1162   public void setRawKVBatchReadSlowLogInMS(Integer rawKVBatchReadSlowLogInMS) {
1163     this.rawKVBatchReadSlowLogInMS = rawKVBatchReadSlowLogInMS;
1164   }
1165 
1166   public Integer getRawKVBatchWriteSlowLogInMS() {
1167     return Optional.ofNullable(rawKVBatchWriteSlowLogInMS).orElse((int) (getTimeout() * 2));
1168   }
1169 
1170   public void setRawKVBatchWriteSlowLogInMS(Integer rawKVBatchWriteSlowLogInMS) {
1171     this.rawKVBatchWriteSlowLogInMS = rawKVBatchWriteSlowLogInMS;
1172   }
1173 
1174   public int getRawKVScanSlowLogInMS() {
1175     return rawKVScanSlowLogInMS;
1176   }
1177 
1178   public void setRawKVScanSlowLogInMS(int rawKVScanSlowLogInMS) {
1179     this.rawKVScanSlowLogInMS = rawKVScanSlowLogInMS;
1180   }
1181 
1182   public double getRawKVServerSlowLogFactor() {
1183     return rawKVServerSlowLogFactor;
1184   }
1185 
1186   public void setRawKVServerSlowLogFactor(double rawKVServerSlowLogFactor) {
1187     if (rawKVServerSlowLogFactor < 0 || rawKVServerSlowLogFactor > 1) {
1188       throw new IllegalArgumentException("rawkv_server_slowlog_factor must be in range [0, 1]");
1189     }
1190     this.rawKVServerSlowLogFactor = rawKVServerSlowLogFactor;
1191   }
1192 
1193   public boolean isCircuitBreakEnable() {
1194     return circuitBreakEnable;
1195   }
1196 
1197   public void setCircuitBreakEnable(boolean circuitBreakEnable) {
1198     this.circuitBreakEnable = circuitBreakEnable;
1199   }
1200 
1201   public int getCircuitBreakAvailabilityWindowInSeconds() {
1202     return circuitBreakAvailabilityWindowInSeconds;
1203   }
1204 
1205   public void setCircuitBreakAvailabilityWindowInSeconds(
1206       int circuitBreakAvailabilityWindowInSeconds) {
1207     this.circuitBreakAvailabilityWindowInSeconds = circuitBreakAvailabilityWindowInSeconds;
1208   }
1209 
1210   public int getCircuitBreakAvailabilityErrorThresholdPercentage() {
1211     return circuitBreakAvailabilityErrorThresholdPercentage;
1212   }
1213 
1214   public void setCircuitBreakAvailabilityErrorThresholdPercentage(
1215       int circuitBreakAvailabilityErrorThresholdPercentage) {
1216     this.circuitBreakAvailabilityErrorThresholdPercentage =
1217         circuitBreakAvailabilityErrorThresholdPercentage;
1218   }
1219 
1220   public int getCircuitBreakAvailabilityRequestVolumnThreshold() {
1221     return circuitBreakAvailabilityRequestVolumnThreshold;
1222   }
1223 
1224   public void setCircuitBreakAvailabilityRequestVolumnThreshold(
1225       int circuitBreakAvailabilityRequestVolumnThreshold) {
1226     this.circuitBreakAvailabilityRequestVolumnThreshold =
1227         circuitBreakAvailabilityRequestVolumnThreshold;
1228   }
1229 
1230   public int getCircuitBreakSleepWindowInSeconds() {
1231     return circuitBreakSleepWindowInSeconds;
1232   }
1233 
1234   public void setCircuitBreakSleepWindowInSeconds(int circuitBreakSleepWindowInSeconds) {
1235     this.circuitBreakSleepWindowInSeconds = circuitBreakSleepWindowInSeconds;
1236   }
1237 
1238   public int getCircuitBreakAttemptRequestCount() {
1239     return circuitBreakAttemptRequestCount;
1240   }
1241 
1242   public void setCircuitBreakAttemptRequestCount(int circuitBreakAttemptRequestCount) {
1243     this.circuitBreakAttemptRequestCount = circuitBreakAttemptRequestCount;
1244   }
1245 
1246   public int getScanRegionsLimit() {
1247     return scanRegionsLimit;
1248   }
1249 
1250   public void setScanRegionsLimit(int scanRegionsLimit) {
1251     this.scanRegionsLimit = scanRegionsLimit;
1252   }
1253 
1254   public ApiVersion getApiVersion() {
1255     return apiVersion;
1256   }
1257 
1258   public TiConfiguration setApiVersion(ApiVersion version) {
1259     this.apiVersion = version;
1260     return this;
1261   }
1262 
1263   public enum ApiVersion {
1264     V1,
1265     V2;
1266 
1267     public static ApiVersion fromInt(int version) {
1268       switch (version) {
1269         case 1:
1270           return V1;
1271         case 2:
1272           return V2;
1273         default:
1274           throw new IllegalArgumentException("unknown api version " + version);
1275       }
1276     }
1277 
1278     public boolean isV1() {
1279       return this == V1;
1280     }
1281 
1282     public boolean isV2() {
1283       return this == V2;
1284     }
1285 
1286     public Kvrpcpb.APIVersion toPb() {
1287       switch (this) {
1288         case V1:
1289           return Kvrpcpb.APIVersion.V1;
1290         case V2:
1291           return Kvrpcpb.APIVersion.V2;
1292         default:
1293           throw new IllegalArgumentException("unknown api version " + this);
1294       }
1295     }
1296   }
1297 }