Files
oceanbase/src/share/config/ob_config_helper.cpp
2024-06-26 09:17:10 +00:00

1352 lines
42 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "share/config/ob_config_helper.h"
#include "share/config/ob_config.h"
#include "lib/ob_running_mode.h"
#include "lib/utility/ob_macro_utils.h"
#include "lib/compress/ob_compressor_pool.h"
#include "lib/resource/achunk_mgr.h"
#include "rpc/obrpc/ob_rpc_packet.h"
#include "common/ob_store_format.h"
#include "common/ob_smart_var.h"
#include "share/config/ob_server_config.h"
#include "sql/monitor/ob_security_audit_utils.h"
#include "observer/ob_server_struct.h"
#include "share/ob_rpc_struct.h"
#include "sql/plan_cache/ob_plan_cache_util.h"
#include "sql/optimizer/ob_log_join_filter.h"
#include "share/ob_encryption_util.h"
#include "share/ob_resource_limit.h"
#include "share/table/ob_ttl_util.h"
#include "src/observer/ob_server.h"
#include "share/table/ob_table_config_util.h"
#include "share/config/ob_config_mode_name_def.h"
#include "share/schema/ob_schema_struct.h"
#include "share/ob_ddl_common.h"
#include "share/backup/ob_archive_persist_helper.h"
namespace oceanbase
{
using namespace share;
using namespace obrpc;
namespace common
{
bool ObConfigIpChecker::check(const ObConfigItem &t) const
{
struct sockaddr_in sa;
int result = inet_pton(AF_INET, t.str(), &(sa.sin_addr));
return result != 0;
}
ObConfigConsChecker:: ~ObConfigConsChecker()
{
if (NULL != left_) {
ObConfigChecker *left = const_cast<ObConfigChecker*>(left_);
OB_DELETE(ObConfigChecker, "unused", left);
}
if (NULL != right_) {
ObConfigChecker *right = const_cast<ObConfigChecker*>(right_);
OB_DELETE(ObConfigChecker, "unused", right);
}
}
bool ObConfigConsChecker::check(const ObConfigItem &t) const
{
return (NULL == left_ ? true : left_->check(t))
&& (NULL == right_ ? true : right_->check(t));
}
bool ObConfigEvenIntChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.str(), is_valid);
if (is_valid) {
is_valid = value % 2 == 0;
}
return is_valid;
}
bool ObConfigFreezeTriggerIntChecker::check(const uint64_t tenant_id,
const ObAdminSetConfigItem &t)
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
int64_t write_throttle_trigger = get_write_throttle_trigger_percentage_(tenant_id);
if (is_valid) {
is_valid = value > 0 && value < 100;
}
if (is_valid) {
is_valid = write_throttle_trigger != 0;
}
if (is_valid) {
is_valid = value < write_throttle_trigger;
}
return is_valid;
}
int64_t ObConfigFreezeTriggerIntChecker::get_write_throttle_trigger_percentage_(const uint64_t tenant_id)
{
int64_t percent = 0;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id));
if (tenant_config.is_valid()) {
percent = tenant_config->writing_throttling_trigger_percentage;
}
return percent;
}
bool ObConfigTxShareMemoryLimitChecker::check(const uint64_t tenant_id, const ObAdminSetConfigItem &t)
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
int64_t cluster_memstore_limit = GCONF.memstore_limit_percentage;
int64_t memstore_limit = 0;
int64_t tx_data_limit = 0;
int64_t mds_limit = 0;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id));
if (tenant_config.is_valid()) {
memstore_limit = tenant_config->_memstore_limit_percentage;
tx_data_limit = tenant_config->_tx_data_memory_limit_percentage;
mds_limit = tenant_config->_mds_memory_limit_percentage;
} else {
is_valid = false;
OB_LOG_RET(ERROR, OB_INVALID_CONFIG, "tenant config is invalid", K(tenant_id));
}
if (0 == memstore_limit) {
memstore_limit = cluster_memstore_limit;
}
if (!is_valid) {
} else if (0 == memstore_limit) {
// both 0 means adjust the percentage automatically.
is_valid = true;
} else if (0 == value) {
// 0 is default value, which means (_tx_share_memory_limit_percentage = memstore_limit_percentage + 10)
is_valid = true;
} else if ((value > 0 && value < 100) && (memstore_limit <= value) && (tx_data_limit <= value) &&
(mds_limit <= value)) {
is_valid = true;
} else {
is_valid = false;
}
if (!is_valid) {
OB_LOG_RET(WARN, OB_INVALID_CONFIG,
"update _tx_share_memory_limit_percentage failed",
"_tx_share_memory_limit_percentage", value,
"memstore_limit_percentage", memstore_limit,
"_tx_data_memory_limit_percentage", tx_data_limit,
"_mds_memory_limit_percentage", mds_limit);
}
return is_valid;
}
bool less_or_equal_tx_share_limit(const uint64_t tenant_id, const int64_t value)
{
bool bool_ret = true;
int64_t tx_share_limit = 0;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id));
if (tenant_config.is_valid()) {
tx_share_limit = tenant_config->_tx_share_memory_limit_percentage;
if (0 == value) {
// 0 is default value, which means memstore limit percentage will adjust itself.
bool_ret = true;
} else if (0 == tx_share_limit) {
// 0 is default value, which means (_tx_share_memory_limit_percentage = memstore_limit_percentage + 10)
bool_ret = true;
} else if (value > 0 && value < 100 && value <= tx_share_limit) {
bool_ret = true;
} else {
bool_ret = false;
}
} else {
bool_ret = false;
OB_LOG_RET(ERROR, OB_INVALID_CONFIG, "tenant config is invalid", K(tenant_id));
}
return bool_ret;
}
bool ObConfigMemstoreLimitChecker::check(const uint64_t tenant_id, const obrpc::ObAdminSetConfigItem &t)
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
if (less_or_equal_tx_share_limit(tenant_id, value)) {
is_valid = true;
} else {
is_valid = false;
}
return is_valid;
}
bool ObConfigTxDataLimitChecker::check(const uint64_t tenant_id, const obrpc::ObAdminSetConfigItem &t)
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
if (less_or_equal_tx_share_limit(tenant_id, value)) {
is_valid = true;
} else {
is_valid = false;
}
return is_valid;
}
bool ObConfigMdsLimitChecker::check(const uint64_t tenant_id, const obrpc::ObAdminSetConfigItem &t)
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
if (less_or_equal_tx_share_limit(tenant_id, value)) {
is_valid = true;
} else {
is_valid = false;
}
return is_valid;
}
bool ObConfigWriteThrottleTriggerIntChecker::check(const uint64_t tenant_id,
const ObAdminSetConfigItem &t)
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
int64_t freeze_trigger = get_freeze_trigger_percentage_(tenant_id);
if (is_valid) {
is_valid = value > 0 && value <= 100;
}
if (is_valid) {
is_valid = freeze_trigger != 0;
}
if (is_valid) {
is_valid = value > freeze_trigger;
}
return is_valid;
}
int64_t ObConfigWriteThrottleTriggerIntChecker::get_freeze_trigger_percentage_(const uint64_t tenant_id)
{
int64_t percent = 0;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id));
if (tenant_config.is_valid()) {
percent = tenant_config->freeze_trigger_percentage;
}
return percent;
}
bool ObConfigLogDiskLimitThresholdIntChecker::check(const uint64_t tenant_id,
const ObAdminSetConfigItem &t)
{
bool is_valid = false;
const int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
const int64_t throttling_percentage = get_log_disk_throttling_percentage_(tenant_id);
if (is_valid) {
is_valid = (throttling_percentage != 0);
}
if (is_valid) {
is_valid = (throttling_percentage == 100) || (value > throttling_percentage);
}
return is_valid;
}
int64_t ObConfigLogDiskLimitThresholdIntChecker::get_log_disk_throttling_percentage_(const uint64_t tenant_id)
{
int64_t percent = 0;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id));
if (tenant_config.is_valid()) {
percent = tenant_config->log_disk_throttling_percentage;
}
return percent;
}
bool ObConfigLogDiskThrottlingPercentageIntChecker::check(const uint64_t tenant_id, const obrpc::ObAdminSetConfigItem &t)
{
bool is_valid = false;
const int64_t value = ObConfigIntParser::get(t.value_.ptr(), is_valid);
const int64_t limit_threshold = get_log_disk_utilization_limit_threshold_(tenant_id);
if (is_valid) {
is_valid = (limit_threshold != 0);
}
if (is_valid) {
is_valid = (value == 100) || (value < limit_threshold);
}
return is_valid;
}
int64_t ObConfigLogDiskThrottlingPercentageIntChecker::get_log_disk_utilization_limit_threshold_(const uint64_t tenant_id)
{
int64_t threshold = 0;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id));
if (tenant_config.is_valid()) {
threshold = tenant_config->log_disk_utilization_limit_threshold;
}
return threshold;
}
bool ObConfigTabletSizeChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
const int64_t mask = (1 << 21) - 1;
int64_t value = ObConfigCapacityParser::get(t.str(), is_valid, false);
if (is_valid) {
// value has to be a multiple of 2M
is_valid = (value >= 0) && !(value & mask);
}
return is_valid;
}
bool ObConfigStaleTimeChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t stale_time = ObConfigTimeParser::get(t.str(), is_valid);
if (is_valid) {
is_valid = (stale_time >= GCONF.weak_read_version_refresh_interval);
if (!is_valid) {
LOG_USER_ERROR(OB_NOT_SUPPORTED, "max_stale_time_for_weak_consistency violate"
" weak_read_version_refresh_interval,");
}
}
return is_valid;
}
bool ObConfigCompressFuncChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int i = 0; i < ARRAYSIZEOF(common::compress_funcs); ++i) {
if (0 == ObString::make_string(compress_funcs[i]).case_compare(t.str())) {
if (i != DISABLED_ZLIB_1_COMPRESS_IDX) {
is_valid = true;
}
break;
}
}
return is_valid;
}
bool ObConfigPerfCompressFuncChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int i = 0; i < ARRAYSIZEOF(common::perf_compress_funcs) && !is_valid; ++i) {
if (0 == ObString::make_string(perf_compress_funcs[i]).case_compare(t.str())) {
is_valid = true;
}
}
return is_valid;
}
bool ObConfigResourceLimitSpecChecker::check(const ObConfigItem &t) const
{
ObResourceLimit rl;
int ret = rl.load_config(t.str());
return OB_SUCCESS == ret;
}
bool ObConfigTempStoreFormatChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int i = 0; i < ARRAYSIZEOF(share::temp_store_format_options) && !is_valid; ++i) {
if (0 == ObString::make_string(temp_store_format_options[i]).case_compare(t.str())) {
is_valid = true;
}
}
return is_valid;
}
bool ObConfigPxBFGroupSizeChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
ObString str("auto");
if (0 == str.case_compare(t.str())) {
is_valid = true;
// max_number: 2^64 - 1
} else if (strlen(t.str()) <= 20 && strlen(t.str()) > 0) {
is_valid = true;
for (int i = 0; i < strlen(t.str()); ++i) {
if (0 == i && (t.str()[i] <= '0' || t.str()[i] > '9')) {
is_valid = false;
break;
} else if (t.str()[i] < '0' || t.str()[i] > '9') {
is_valid = false;
break;
}
}
}
return is_valid;
}
bool ObConfigRowFormatChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
ObStoreFormatType type = OB_STORE_FORMAT_INVALID;
if (OB_ISNULL(t.str()) || strlen(t.str()) == 0) {
} else if (OB_SUCCESS != ObStoreFormat::find_store_format_type_mysql(ObString::make_string(t.str()), type)) {
} else if (ObStoreFormat::is_store_format_mysql(type)) {
is_valid = true;
}
return is_valid;
}
bool ObConfigCompressOptionChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
ObStoreFormatType type = OB_STORE_FORMAT_INVALID;
if (OB_ISNULL(t.str()) || strlen(t.str()) == 0) {
} else if (OB_SUCCESS != ObStoreFormat::find_store_format_type_oracle(ObString::make_string(t.str()), type)) {
} else if (ObStoreFormat::is_store_format_oracle(type)) {
is_valid = true;
}
return is_valid;
}
bool ObConfigMaxSyslogFileCountChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t max_count = ObConfigIntParser::get(t.str(), is_valid);
if (is_valid) {
int64_t uncompressed_count = GCONF.syslog_file_uncompressed_count;
if (max_count == 0 || max_count >= uncompressed_count) {
is_valid = true;
} else {
is_valid = false;
}
}
return is_valid;
}
bool ObConfigSyslogCompressFuncChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int i = 0; i < ARRAYSIZEOF(common::syslog_compress_funcs) && !is_valid; ++i) {
if (0 == ObString::make_string(syslog_compress_funcs[i]).case_compare(t.str())) {
is_valid = true;
}
}
return is_valid;
}
bool ObConfigSyslogFileUncompressedCountChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t uncompressed_count = ObConfigIntParser::get(t.str(), is_valid);
if (is_valid) {
int64_t max_count = GCONF.max_syslog_file_count;
if (uncompressed_count >= 0 && (max_count == 0 || uncompressed_count <= max_count)) {
is_valid = true;
} else {
is_valid = false;
}
}
return is_valid;
}
bool ObConfigLogLevelChecker::check(const ObConfigItem &t) const
{
const ObString tmp_str(t.str());
return ((0 == tmp_str.case_compare(ObLogger::PERF_LEVEL))
|| OB_SUCCESS == OB_LOGGER.parse_check(tmp_str.ptr(), tmp_str.length()));
}
bool ObConfigAlertLogLevelChecker::check(const ObConfigItem &t) const
{
const ObString tmp_str(t.str());
return OB_SUCCESS == OB_LOGGER.parse_check_alert(tmp_str.ptr(), tmp_str.length());
}
bool ObConfigAuditTrailChecker::check(const ObConfigItem &t) const
{
common::ObString tmp_string(t.str());
return sql::get_audit_trail_type_from_string(tmp_string) != sql::ObAuditTrailType::INVALID ;
}
bool ObConfigWorkAreaPolicyChecker::check(const ObConfigItem &t) const
{
const ObString tmp_str(t.str());
return ((0 == tmp_str.case_compare(MANUAL)) || (0 == tmp_str.case_compare(AUTO)));
}
bool ObConfigLogArchiveOptionsChecker::check(const ObConfigItem &t) const
{
bool bret = true;
int ret = OB_SUCCESS;
SMART_VAR(char[OB_MAX_CONFIG_VALUE_LEN], tmp_str) {
const size_t str_len = STRLEN(t.str());
MEMCPY(tmp_str, t.str(), str_len);
tmp_str[str_len] = 0;
const int64_t FORMAT_BUF_LEN = str_len * 3;// '=' will be replaced with ' = '
char format_str_buf[FORMAT_BUF_LEN];
int ret = OB_SUCCESS;
//first replace '=' with ' = '
if (OB_FAIL(ObConfigLogArchiveOptionsItem::format_option_str(tmp_str,
str_len,
format_str_buf,
FORMAT_BUF_LEN))) {
bret = false;
OB_LOG(WARN, "failed to format_option_str", KR(bret), K(tmp_str));
} else {
char *saveptr = NULL;
char *s = STRTOK_R(format_str_buf, " ", &saveptr);
bool is_equal_sign_demanded = false;
int64_t key_idx = -1;
if (OB_LIKELY(NULL != s)) {
do {
if (is_equal_sign_demanded) {
if (0 == ObString::make_string("=").case_compare(s)) {
is_equal_sign_demanded = false;
} else {
OB_LOG(WARN, " '=' is expected", K(s));
bret = false;
}
} else if (key_idx < 0) {
int64_t idx = ObConfigLogArchiveOptionsItem::get_keywords_idx(s, is_equal_sign_demanded);
if (idx < 0) {
bret = false;
OB_LOG(WARN, " not expected isolate option", K(s));
} else if (is_equal_sign_demanded) {
key_idx = idx;
} else {
key_idx = -1;
bret = ObConfigLogArchiveOptionsItem::is_valid_isolate_option(idx);
}
} else if (LOG_ARCHIVE_COMPRESSION_IDX == key_idx) {
if (-1 == ObConfigLogArchiveOptionsItem::get_compression_option_idx(s)) {
OB_LOG(WARN, "failed to get_compression_option_idx", K(key_idx), K(s));
bret = false;
}
key_idx = -1;
} else if (LOG_ARCHIVE_ENCRYPTION_MODE_IDX == key_idx) {
ObBackupEncryptionMode::EncryptionMode mode = ObBackupEncryptionMode::parse_str(s);
if (!ObBackupEncryptionMode::is_valid_for_log_archive(mode)) {
OB_LOG(WARN, "invalid encrytion mode", K(mode));
bret = false;
}
key_idx = -1;
} else if (LOG_ARCHIVE_ENCRYPTION_ALGORITHM_IDX == key_idx) {
share::ObCipherOpMode encryption_algorithm;
if (OB_FAIL(ObEncryptionUtil::parse_encryption_algorithm(s, encryption_algorithm))) {
bret = false;
OB_LOG(WARN, "invalid encrytion algorithm", K(s));
}
key_idx = -1;
} else {
OB_LOG(WARN, "invalid key_idx", K(key_idx), K(s));
bret = false;
}
} while (OB_LIKELY(NULL != (s = STRTOK_R(NULL, " ", &saveptr))) && bret);
if (key_idx >= 0) {
bret = false;
OB_LOG(WARN, "kv option is not compelte", K(tmp_str));
}
} else {
bret = false;
OB_LOG(WARN, "invalid config value", K(tmp_str));
}
}
}
return bret;
}
bool ObConfigRpcChecksumChecker::check(const ObConfigItem &t) const
{
common::ObString tmp_string(t.str());
return obrpc::get_rpc_checksum_check_level_from_string(tmp_string) != obrpc::ObRpcCheckSumCheckLevel::INVALID ;
}
bool ObTTLDutyDurationChecker::check(const ObConfigItem& t) const
{
common::ObTTLDutyDuration duty_duration;
return OB_SUCCESS == common::ObTTLUtil::parse(t.str(), duty_duration) && duty_duration.is_valid();
}
bool ObConfigPublishSchemaModeChecker::check(const ObConfigItem& t) const
{
return 0 == t.case_compare(PUBLISH_SCHEMA_MODE_BEST_EFFORT)
|| 0 == t.case_compare(PUBLISH_SCHEMA_MODE_ASYNC);
}
bool ObConfigMemoryLimitChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t value = ObConfigCapacityParser::get(t.str(), is_valid, false);
if (is_valid) {
int64_t min_memory_size = OBSERVER.is_arbitration_mode() ? lib::ObRunningModeConfig::instance().MIN_MEM :
lib::ObRunningModeConfig::instance().MINI_MEM_LOWER;
is_valid = 0 == value || value >= min_memory_size;
}
return is_valid;
}
bool ObConfigTenantMemoryChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t value = ObConfigCapacityParser::get(t.str(), is_valid);
if (is_valid) {
is_valid = 0 == value || (value >= ObUnitResource::UNIT_MIN_MEMORY);
}
return is_valid;
}
bool ObConfigQueryRateLimitChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.str(), is_valid);
if (is_valid) {
is_valid = (-1 == value ||
(value >= MIN_QUERY_RATE_LIMIT &&
value <= MAX_QUERY_RATE_LIMIT));
}
return is_valid;
}
const char *ObConfigPartitionBalanceStrategyFuncChecker::balance_strategy[
ObConfigPartitionBalanceStrategyFuncChecker::PARTITION_BALANCE_STRATEGY_MAX] = {
"auto",
"standard",
"disk_utilization_only",
};
bool ObConfigPartitionBalanceStrategyFuncChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int64_t i = 0; i < ARRAYSIZEOF(balance_strategy) && !is_valid; ++i) {
if (0 == ObString::make_string(balance_strategy[i]).case_compare(t.str())) {
is_valid = true;
}
}
return is_valid;
}
bool ObDataStorageErrorToleranceTimeChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t value = ObConfigTimeParser::get(t.str(), is_valid);
if (is_valid) {
const int64_t warning_value = GCONF.data_storage_warning_tolerance_time;
is_valid = value >= warning_value;
}
return is_valid;
}
bool ObConfigOfsBlockVerifyIntervalChecker::check(const ObConfigItem &t) const
{
bool is_valid = true;
int64_t value = ObConfigTimeParser::get(t.str(), is_valid);
if (is_valid) {
is_valid = (0 == value) || (value >= MIN_VALID_INTVL && value <= MAX_VALID_INTVL);
}
return is_valid;
}
bool ObLogDiskUsagePercentageChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.str(), is_valid);
if (is_valid) {
// TODO by runlun: 租户级配置项检查
const int64_t log_disk_utilization_threshold = 100;
if (value < log_disk_utilization_threshold) {
is_valid = false;
LOG_USER_ERROR(OB_INVALID_CONFIG,
"log_disk_utilization_limit_threshold "
"should not be less than log_disk_utilization_threshold");
}
}
return is_valid;
}
bool ObConfigEnableDefensiveChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
int64_t value = ObConfigIntParser::get(t.str(), is_valid);
if (is_valid) {
if (value > 2 || value < 0) {
is_valid = false;
}
}
return is_valid;
}
int64_t ObConfigIntParser::get(const char *str, bool &valid)
{
char *p_end = NULL;
int64_t value = 0;
if (OB_ISNULL(str) || '\0' == str[0]) {
valid = false;
} else {
valid = true;
value = strtol(str, &p_end, 0);
if ('\0' == *p_end) {
valid = true;
} else {
valid = false;
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "set int error", K(str), K(valid));
}
}
return value;
}
int64_t ObConfigCapacityParser::get(const char *str, bool &valid,
bool check_unit /* = true */,
bool use_byte /* = false*/)
{
char *p_unit = NULL;
int64_t value = 0;
if (OB_ISNULL(str) || '\0' == str[0]) {
valid = false;
} else {
valid = true;
value = strtol(str, &p_unit, 0);
if (OB_ISNULL(p_unit)) {
valid = false;
} else if (value < 0) {
valid = false;
} else if ('\0' == *p_unit) {
if (check_unit) {
valid = false;
} else if (!use_byte) {
value <<= CAP_MB;
}
} else if (0 == STRCASECMP("b", p_unit) || 0 == STRCASECMP("byte", p_unit)) {
// do nothing
} else if (0 == STRCASECMP("kb", p_unit) || 0 == STRCASECMP("k", p_unit)) {
value <<= CAP_KB;
} else if (0 == STRCASECMP("mb", p_unit) || 0 == STRCASECMP("m", p_unit)) {
value <<= CAP_MB;
} else if (0 == STRCASECMP("gb", p_unit) || 0 == STRCASECMP("g", p_unit)) {
value <<= CAP_GB;
} else if (0 == STRCASECMP("tb", p_unit) || 0 == STRCASECMP("t", p_unit)) {
value <<= CAP_TB;
} else if (0 == STRCASECMP("pb", p_unit) || 0 == STRCASECMP("p", p_unit)) {
value <<= CAP_PB;
} else {
valid = false;
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "get capacity error", K(str), K(p_unit));
}
}
return value;
}
int64_t ObConfigReadableIntParser::get(const char *str, bool &valid)
{
char *p_unit = NULL;
int64_t value = 0;
if (OB_ISNULL(str) || '\0' == str[0]) {
valid = false;
} else {
valid = true;
value = strtol(str, &p_unit, 0);
if (OB_ISNULL(p_unit)) {
valid = false;
} else if (value < 0) {
valid = false;
} else if ('\0' == *p_unit) {
//
// without any unit, do nothing
} else if (0 == STRCASECMP("k", p_unit)) {
value *= UNIT_K;
} else if (0 == STRCASECMP("m", p_unit)) {
value *= UNIT_M;
} else {
valid = false;
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "set readable int error", K(str), K(p_unit));
}
}
return value;
}
int64_t ObConfigTimeParser::get(const char *str, bool &valid)
{
char *p_unit = NULL;
int64_t value = 0;
if (OB_ISNULL(str) || '\0' == str[0]) {
valid = false;
} else {
valid = true;
value = strtol(str, &p_unit, 0);
if (OB_ISNULL(p_unit)) {
valid = false;
} else if (value < 0) {
valid = false;
} else if (0 == STRCASECMP("us", p_unit)) {
value = value * TIME_MICROSECOND;
} else if (0 == STRCASECMP("ms", p_unit)) {
value = value * TIME_MILLISECOND;
} else if ('\0' == *p_unit || 0 == STRCASECMP("s", p_unit)) {
value = value * TIME_SECOND;
} else if (0 == STRCASECMP("m", p_unit)) {
value = value * TIME_MINUTE;
} else if (0 == STRCASECMP("h", p_unit)) {
value = value * TIME_HOUR;
} else if (0 == STRCASECMP("d", p_unit)) {
value = value * TIME_DAY;
} else {
valid = false;
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "set time error", K(str), K(p_unit));
}
}
return value;
}
bool ObConfigUpgradeStageChecker::check(const ObConfigItem &t) const
{
obrpc::ObUpgradeStage stage = obrpc::get_upgrade_stage(t.str());
return obrpc::OB_UPGRADE_STAGE_INVALID < stage
&& obrpc::OB_UPGRADE_STAGE_MAX > stage;
}
bool ObConfigPlanCacheGCChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int i = 0; i < ARRAYSIZEOF(sql::plan_cache_gc_confs) && !is_valid; i++) {
if (0 == ObString::make_string(sql::plan_cache_gc_confs[i]).case_compare(t.str())) {
is_valid = true;
}
}
return is_valid;
}
bool ObConfigUseLargePagesChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int i = 0; i < ARRAYSIZEOF(lib::use_large_pages_confs) && !is_valid; i++) {
if (0 == ObString::make_string(lib::use_large_pages_confs[i]).case_compare(t.str())) {
is_valid = true;
}
}
return is_valid;
}
bool ObConfigAuditModeChecker::check(const ObConfigItem &t) const
{
ObString v_str(t.str());
return 0 == v_str.case_compare("NONE") ||
0 == v_str.case_compare("ORACLE") ||
0 == v_str.case_compare("MYSQL");
}
bool ObConfigBoolParser::get(const char *str, bool &valid)
{
bool value = true;
valid = false;
if (OB_ISNULL(str)) {
valid = false;
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "Get bool config item fail, str is NULL!");
} else if (0 == STRCASECMP(str, "false")) {
valid = true;
value = false;
} else if (0 == STRCASECMP(str, "true")) {
valid = true;
value = true;
} else if (0 == STRCASECMP(str, "off")) {
valid = true;
value = false;
} else if (0 == STRCASECMP(str, "on")) {
valid = true;
value = true;
} else if (0 == STRCASECMP(str, "no")) {
valid = true;
value = false;
} else if (0 == STRCASECMP(str, "yes")) {
valid = true;
value = true;
} else if (0 == STRCASECMP(str, "f")) {
valid = true;
value = false;
} else if (0 == STRCASECMP(str, "t")) {
valid = true;
value = true;
} else if (0 == STRCASECMP(str, "1")) {
valid = true;
value = true;
} else if (0 == STRCASECMP(str, "0")) {
valid = true;
value = false;
} else {
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "Get bool config item fail", K(str));
valid = false;
}
return value;
}
bool ObCtxMemoryLimitChecker::check(const ObConfigItem &t) const
{
uint64_t ctx_id = 0;
int64_t limit = 0;
return check(t.str(), ctx_id, limit);
}
bool ObCtxMemoryLimitChecker::check(const char* str, uint64_t& ctx_id, int64_t& limit) const
{
bool is_valid = false;
ctx_id = 0;
limit = 0;
if ('\0' == str[0]) {
is_valid = true;
} else {
auto len = STRLEN(str);
for (int64_t i = 0; i + 1 < len && !is_valid; ++i) {
if (':' == str[i]) {
limit = ObConfigCapacityParser::get(str + i + 1, is_valid, false);
if (is_valid) {
int ret = OB_SUCCESS;
SMART_VAR(char[OB_MAX_CONFIG_VALUE_LEN], tmp_str) {
strncpy(tmp_str, str, i);
tmp_str[i] = '\0';
is_valid = get_global_ctx_info().is_valid_ctx_name(tmp_str, ctx_id);
}
}
}
}
}
return is_valid && limit >= 0;
}
bool ObAutoIncrementModeChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
ObString order("order");
ObString noorder("noorder");
if (0 == order.case_compare(t.str()) || 0 == noorder.case_compare(t.str())) {
is_valid = true;
}
return is_valid;
}
bool ObRpcClientAuthMethodChecker::check(const ObConfigItem &t) const
{
ObString v_str(t.str());
return 0 == v_str.case_compare("NONE") ||
0 == v_str.case_compare("SSL_NO_ENCRYPT") ||
0 == v_str.case_compare("SSL_IO");
}
bool ObRpcServerAuthMethodChecker::is_valid_server_auth_method(const ObString &str) const
{
return 0 == str.case_compare("NONE") ||
0 == str.case_compare("SSL_NO_ENCRYPT") ||
0 == str.case_compare("SSL_IO") ||
0 == str.case_compare("ALL");
}
bool ObRpcServerAuthMethodChecker::check(const ObConfigItem &t) const
{
bool bret = true;
int MAX_METHOD_LENGTH = 256;
char tmp_str[MAX_METHOD_LENGTH];
size_t str_len = STRLEN(t.str());
if (str_len >= MAX_METHOD_LENGTH) {
bret = false;
} else {
MEMCPY(tmp_str, t.str(), str_len);
tmp_str[str_len] = 0;
ObString str(str_len, reinterpret_cast<const char *>(tmp_str));
if (NULL == str.find(',')) {
bret = is_valid_server_auth_method(str);
} else {
//split by comma
char *token = NULL;
char *save = NULL;
char *str_token = tmp_str;
int hint = 0;
do {
token = strtok_r(str_token, ",", &save);
str_token = NULL;
if (token) {
hint = 1;
ObString tmp(STRLEN(token), reinterpret_cast<const char *>(token));
ObString tmp_to_check = tmp.trim();
if (is_valid_server_auth_method(tmp_to_check)) {
} else {
bret = false;
break;
}
} else {
if (!hint) {
bret = false;
}
break;
}
} while(true);
}
}
return bret;
}
int64_t ObConfigRuntimeFilterChecker::get_runtime_filter_type(const char *str, int64_t len)
{
int64_t rf_type = -1;
int64_t l = 0, r = len;
if (0 == len) {
rf_type = 0;
} else {
int64_t l = 0, r = len;
bool is_valid = true;
int flag[3] = {0, 0, 0};
auto fill_flag = [&] (ObString &p_str) {
bool valid = true;
ObString trim_str = p_str.trim();
if (0 == trim_str.case_compare("bloom_filter")) {
flag[0]++;
} else if (0 == trim_str.case_compare("range")) {
flag[1]++;
} else if (0 == trim_str.case_compare("in")) {
flag[2]++;
} else {
valid = false;
}
if (valid) {
if (flag[0] > 1 || flag[1] > 1 || flag[2] > 1) {
valid = false;
}
}
return valid;
};
for (int i = 0; i < len && is_valid; ++i) {
if (str[i] == ',') {
r = i;
ObString p_str(r - l, str + l);
is_valid = fill_flag(p_str);
l = i + 1;
continue;
}
}
if (is_valid) {
ObString p_str(len - l, str + l);
is_valid = fill_flag(p_str);
}
if (is_valid) {
rf_type = flag[0] << 1 |
flag[1] << 2 |
flag[2] << 3;
} else {
rf_type = -1;
}
}
return rf_type;
}
bool ObConfigRuntimeFilterChecker::check(const ObConfigItem &t) const
{
int64_t len = strlen(t.str());
const char *p = t.str();
int64_t rf_type = get_runtime_filter_type(t.str(), len);
return rf_type >= 0;
}
bool ObConfigSQLTlsVersionChecker::check(const ObConfigItem &t) const
{
const ObString tmp_str(t.str());
return 0 == tmp_str.case_compare("NONE") ||
0 == tmp_str.case_compare("TLSV1") ||
0 == tmp_str.case_compare("TLSV1.1") ||
0 == tmp_str.case_compare("TLSV1.2") ||
0 == tmp_str.case_compare("TLSV1.3");
}
bool ObSqlPlanManagementModeChecker::check(const ObConfigItem &t) const
{
const ObString tmp_str(t.str());
return get_spm_mode_by_string(tmp_str) != -1;
}
/**
* return spm mode
* -1 represent invalid mode
* 0 represent disable spm
* 1 represent online evolve mode
*/
int64_t ObSqlPlanManagementModeChecker::get_spm_mode_by_string(const common::ObString &string)
{
int64_t spm_mode = -1;
if (string.empty()) {
spm_mode = -1;
} else if (0 == string.case_compare("Disable")) {
spm_mode = 0;
} else if (0 == string.case_compare("OnlineEvolve")) {
spm_mode = 1;
}
return spm_mode;
}
int ObModeConfigParserUitl::parse_item_to_kv(char *item, ObString &key, ObString &value, const char* delim)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(item)) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "item is NULL", K(ret));
} else {
// key
char *save_ptr = NULL;
char *key_ptr = STRTOK_R(item, delim, &save_ptr);
ObString tmp_key(key_ptr);
key = tmp_key.trim();
// value
ObString tmp_value(save_ptr);
value = tmp_value.trim();
if (value.case_compare("on") != 0 && value.case_compare("off") != 0) {
ret = OB_INVALID_CONFIG;
OB_LOG(WARN, "item value is invalid", K(ret), K(value));
}
}
return ret;
}
int ObModeConfigParserUitl::format_mode_str(const char *src, int64_t src_len, char *dst, int64_t dst_len)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(src) || OB_UNLIKELY(src_len <=0)
|| OB_ISNULL(dst) || dst_len < (3 * src_len)) {
ret = OB_INVALID_ARGUMENT;
OB_LOG(WARN, "invalid arguments", KR(ret), KP(src), KP(dst), K(src_len), K(dst_len));
} else {
const char *source_str = src;
const char *locate_str = NULL;
int64_t source_left_len = src_len;
int32_t locate = -1;
int64_t pos = 0;
while (OB_SUCC(ret) && (source_left_len > 0)
&& (NULL != (locate_str = STRCHR(source_str, ',')))) {
locate = static_cast<int32_t>(locate_str - source_str);
if (OB_FAIL(databuff_printf(dst, dst_len, pos, "%.*s , ", locate, source_str))) {
OB_LOG(WARN, "failed to databuff_print", K(ret), K(dst), K(locate), K(source_str));
} else {
source_str = locate_str + 1;
source_left_len -= (locate + 1);
}
}
if (OB_SUCC(ret) && source_left_len > 0) {
if (OB_FAIL(databuff_printf(dst, dst_len, pos, "%s", source_str))) {
OB_LOG(WARN, "failed to databuff_print", KR(ret), K(dst), K(pos));
}
}
OB_LOG(DEBUG, "format_option_str", K(ret), K(src), K(dst));
}
return ret;
}
int ObModeConfigParserUitl::get_kv_list(char *str, ObIArray<std::pair<ObString, ObString>> &kv_list, const char* delim)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(str)) {
ret = OB_ERR_UNEXPECTED;
OB_LOG(WARN, "item is NULL", K(ret));
} else {
ObString key;
ObString value;
char *save_ptr = NULL;
char *token = STRTOK_R(str, ",", &save_ptr);
while (OB_SUCC(ret) && OB_NOT_NULL(token)) {
// trim left space
while (*token == ' ') token++;
// trim right space
uint64_t len = strlen(token);
while (len > 0 && token[len - 1] == ' ') token[--len] = '\0';
// check and set mode
if (OB_FAIL(parse_item_to_kv(token, key, value, delim))) {
OB_LOG(WARN, "fail to check config item", K(ret));
} else if (OB_FAIL(kv_list.push_back(std::make_pair(key, value)))) {
OB_LOG(WARN, "fail to push back key and value pair", K(ret), K(key), K(value));
} else {
token = STRTOK_R(NULL, ",", &save_ptr);
}
}
}
return ret;
}
bool ObKvFeatureModeParser::parse(const char *str, uint8_t *arr, int64_t len)
{
bool bret = true;
if (str == NULL || arr == NULL) {
bret = false;
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "Get mode config item fail, str or value arr is NULL!");
} else if (strlen(str) == 0) {
bret = true;
OB_LOG_RET(DEBUG, OB_SUCCESS, "strlen is 0");
} else {
int tmp_ret = OB_SUCCESS;
ObSEArray<std::pair<ObString, ObString>, 8> kv_list;
int64_t str_len = strlen(str);
const int64_t buf_len = 3 * str_len; // need replace ',' to ' , '
char buf[buf_len];
MEMSET(buf, 0, sizeof(buf));
MEMCPY(buf, str, str_len);
if (OB_SUCCESS != (tmp_ret = ObModeConfigParserUitl::format_mode_str(str, str_len, buf, buf_len))) {
bret = false;
OB_LOG_RET(WARN, tmp_ret, "fail to format mode str", K(str));
} else if (OB_SUCCESS != (tmp_ret = ObModeConfigParserUitl::get_kv_list(buf, kv_list))) {
bret = false;
OB_LOG_RET(WARN, tmp_ret, "fail to get kv list", K(str));
} else {
ObKVFeatureMode kv_mode;
for (int64_t i = 0; i < kv_list.count() && bret; i++) {
uint8_t mode = MODE_DEFAULT;
if (kv_list.at(i).second.case_compare(MODE_VAL_ON) == 0) {
mode = MODE_ON;
} else if (kv_list.at(i).second.case_compare(MODE_VAL_OFF) == 0) {
mode = MODE_OFF;
} else {
bret = false;
OB_LOG_RET(WARN, OB_INVALID_CONFIG, "unknown mode type", K(kv_list.at(i).second));
}
if (!bret) {
} else if (kv_list.at(i).first.case_compare(MODE_NAME_TTL) == 0) {
kv_mode.set_ttl_mode(mode);
} else if (kv_list.at(i).first.case_compare(MODE_NAME_REROUTING) == 0) {
kv_mode.set_rerouting_mode(mode);
} else if (kv_list.at(i).first.case_compare(MODE_NAME_HOTKEY) == 0) {
kv_mode.set_hotkey_mode(mode);
} else {
bret = false;
OB_LOG_RET(WARN, OB_INVALID_CONFIG, "unknown mode name", K(kv_list.at(i).first));
}
} // end for
if (bret) {
arr[0] = kv_mode.get_value();
}
}
}
return bret;
}
bool ObConfigIndexStatsModeChecker::check(const ObConfigItem &t) const {
const ObString tmp_str(t.str());
return 0 == tmp_str.case_compare("SAMPLED") || 0 == tmp_str.case_compare("ALL");
}
bool ObConfigTableStoreFormatChecker::check(const ObConfigItem &t) const {
const ObString tmp_str(t.str());
return 0 == tmp_str.case_compare("ROW") || 0 == tmp_str.case_compare("COLUMN") ||
0 == tmp_str.case_compare("COMPOUND");
}
bool ObConfigMigrationChooseSourceChecker::check(const ObConfigItem &t) const
{
ObString v_str(t.str());
return 0 == v_str.case_compare("idc")
|| 0 == v_str.case_compare("region");
}
bool ObConfigArchiveLagTargetChecker::check(const uint64_t tenant_id, const ObAdminSetConfigItem &t)
{
bool is_valid = false;
int ret = OB_SUCCESS;
int64_t value = ObConfigTimeParser::get(t.value_.ptr(), is_valid);
ObArchivePersistHelper archive_op;
ObBackupPathString archive_dest_str;
ObBackupDest archive_dest;
ObStorageType device_type;
const int64_t dest_no = 0;
const bool lock = false;
if (is_valid) {
if (OB_FAIL(archive_op.init(tenant_id))) {
OB_LOG(WARN, "fail to init archive persist helper", K(ret), K(tenant_id));
} else if (OB_FAIL(archive_op.get_archive_dest(*GCTX.sql_proxy_, lock, dest_no, archive_dest_str))) {
if (OB_ENTRY_NOT_EXIST != ret) {
OB_LOG(WARN, "failed to get archive dest", K(ret), K(tenant_id));
} else { // no dest exist, set archive_lag_target is disallowed
is_valid = false;
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "log_archive_dest has not been set, set archive_lag_target is");
}
} else if (OB_FAIL(archive_dest.set(archive_dest_str))) {
OB_LOG(WARN, "fail to set archive dest", K(ret), K(archive_dest_str));
} else if (archive_dest.is_storage_type_s3()) {
is_valid = MIN_LAG_TARGET_FOR_S3 <= value;
if (!is_valid) {
LOG_USER_ERROR(OB_OP_NOT_ALLOW, "set archive_lag_target smaller than 60s when log_archive_dest is S3 is");
}
} else {
is_valid = true;
}
}
return is_valid;
}
bool ObConfigSQLSpillCompressionCodecChecker::check(const ObConfigItem &t) const
{
bool is_valid = false;
for (int i = 0; i < ARRAYSIZEOF(common::sql_temp_store_compress_funcs) && !is_valid; ++i) {
if (0 == ObString::make_string(sql_temp_store_compress_funcs[i]).case_compare(t.str())) {
is_valid = true;
}
}
return is_valid;
}
bool ObParallelDDLControlParser::parse(const char *str, uint8_t *arr, int64_t len)
{
bool bret = true;
ObParallelDDLControlMode ddl_mode;
if (OB_ISNULL(str) || OB_ISNULL(arr)) {
bret = false;
OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "Get config item failed", KP(str), KP(arr));
} else if (strlen(str) == 0) {
// do nothing
} else {
int tmp_ret = OB_SUCCESS;
ObSEArray<std::pair<ObString, ObString>, 1> kv_list;
int64_t str_len = strlen(str);
const int64_t buf_len = 3 * str_len; // need replace ',' to ' , '
char buf[buf_len];
MEMSET(buf, 0, sizeof(buf));
MEMCPY(buf, str, str_len);
if (OB_TMP_FAIL(ObModeConfigParserUitl::format_mode_str(str, str_len, buf, buf_len))) {
bret = false;
OB_LOG_RET(WARN, tmp_ret, "fail to format mode str", K(str));
} else if (OB_TMP_FAIL(ObModeConfigParserUitl::get_kv_list(buf, kv_list, ":"))) {
bret = false;
OB_LOG_RET(WARN, tmp_ret, "fail to get kv list", K(str));
} else {
for (int64_t i = 0; bret && i < kv_list.count(); ++i) {
uint8_t mode = MODE_DEFAULT;
if (kv_list.at(i).second.case_compare("on") == 0) {
mode = MODE_ON;
} else if (kv_list.at(i).second.case_compare("off") == 0) {
mode = MODE_OFF;
} else {
bret = false;
OB_LOG_RET(WARN, OB_INVALID_CONFIG, "unknown mode type", K(kv_list.at(i).second));
}
ObParallelDDLControlMode::ObParallelDDLType ddl_type = ObParallelDDLControlMode::MAX_TYPE;
if (!bret) {
// do nothing
} else if (OB_TMP_FAIL(ObParallelDDLControlMode::string_to_ddl_type(kv_list.at(i).first, ddl_type))) {
bret = false;
OB_LOG_RET(WARN, tmp_ret, "fail to trans string ddl_type", K(kv_list.at(i).first));
} else if (OB_TMP_FAIL(ddl_mode.set_parallel_ddl_mode(ddl_type, mode))) {
bret = false;
OB_LOG_RET(WARN, tmp_ret, "fail to set parallel ddl mode", K(ddl_type), K(mode));
}
}
}
}
if (bret) {
for (uint64_t i = 0; i < 8; ++i) {
arr[i] = static_cast<uint8_t>((ddl_mode.get_value() >> (i * 8)) & 0xFF);
}
}
return bret;
}
} // end of namepace common
} // end of namespace oceanbase