From e1081698d6c0b7b3180cfa9a360731d3de791ba2 Mon Sep 17 00:00:00 2001 From: GroundWu <1175416256@qq.com> Date: Sat, 9 Sep 2023 11:40:26 +0000 Subject: [PATCH] [OBKV][CP] patch config _obkv_feature_mode from 32x --- src/observer/table/ob_table_rpc_processor.cpp | 21 ++- .../table/ttl/ob_tenant_tablet_ttl_mgr.cpp | 10 +- .../table/ttl/ob_tenant_ttl_manager.cpp | 11 +- src/share/CMakeLists.txt | 1 + src/share/config/ob_config.cpp | 37 +++++ src/share/config/ob_config.h | 52 ++++++ src/share/config/ob_config_helper.cpp | 145 +++++++++++++++- src/share/config/ob_config_helper.h | 34 ++++ src/share/config/ob_config_mode_name_def.h | 28 ++++ src/share/parameter/ob_parameter_macro.h | 18 +- src/share/parameter/ob_parameter_seed.ipp | 4 + src/share/table/ob_table_config_util.cpp | 140 ++++++++++++++++ src/share/table/ob_table_config_util.h | 71 ++++++++ .../resolver/cmd/ob_alter_system_resolver.cpp | 5 + .../all_virtual_sys_parameter_stat.result | 1 + unittest/observer/CMakeLists.txt | 1 + .../observer/tableapi/test_obkv_config.cpp | 156 ++++++++++++++++++ 17 files changed, 721 insertions(+), 14 deletions(-) create mode 100644 src/share/config/ob_config_mode_name_def.h create mode 100644 src/share/table/ob_table_config_util.cpp create mode 100644 src/share/table/ob_table_config_util.h create mode 100644 unittest/observer/tableapi/test_obkv_config.cpp diff --git a/src/observer/table/ob_table_rpc_processor.cpp b/src/observer/table/ob_table_rpc_processor.cpp index bb75c6af53..c4f05f003c 100644 --- a/src/observer/table/ob_table_rpc_processor.cpp +++ b/src/observer/table/ob_table_rpc_processor.cpp @@ -30,6 +30,7 @@ #include "ob_table_session_pool.h" #include "storage/tx/wrs/ob_weak_read_util.h" #include "ob_table_move_response.h" +#include "share/table/ob_table_config_util.h" using namespace oceanbase::observer; using namespace oceanbase::common; @@ -997,13 +998,15 @@ bool oceanbase::observer::is_require_rerouting_err(const int err) { // rerouting: whether client should refresh location cache and retry // Now, following the same logic as in ../mysql/ob_query_retry_ctrl.cpp - return (is_master_changed_error(err) - || is_server_down_error(err) - || is_partition_change_error(err) - || is_server_status_error(err) - || is_unit_migrate(err) - || is_transaction_rpc_timeout_err(err) - || is_has_no_readable_replica_err(err) - || is_select_dup_follow_replic_err(err) - || is_trans_stmt_need_retry_error(err)); + bool is_err = is_master_changed_error(err) + || is_server_down_error(err) + || is_partition_change_error(err) + || is_server_status_error(err) + || is_unit_migrate(err) + || is_transaction_rpc_timeout_err(err) + || is_has_no_readable_replica_err(err) + || is_select_dup_follow_replic_err(err) + || is_trans_stmt_need_retry_error(err); + + return is_err && ObKVFeatureModeUitl::is_rerouting_enable(); } diff --git a/src/observer/table/ttl/ob_tenant_tablet_ttl_mgr.cpp b/src/observer/table/ttl/ob_tenant_tablet_ttl_mgr.cpp index 3c4102e2a2..6bb1ffbef8 100644 --- a/src/observer/table/ttl/ob_tenant_tablet_ttl_mgr.cpp +++ b/src/observer/table/ttl/ob_tenant_tablet_ttl_mgr.cpp @@ -20,6 +20,7 @@ #include "storage/tx_storage/ob_tenant_freezer.h" #include "observer/table/ttl/ob_table_ttl_task.h" #include "observer/table/ob_table_service.h" +#include "share/table/ob_table_config_util.h" namespace oceanbase { @@ -395,6 +396,10 @@ int ObTenantTabletTTLMgr::report_task_status(ObTTLTaskInfo& task_info, ObTTLTask ret = OB_ERR_UNEXPECTED; LOG_WARN("the tablet task ctx is null", KR(ret)); } else { + if (!ObKVFeatureModeUitl::is_ttl_enable()) { + local_tenant_task_.ttl_continue_ = false; + LOG_DEBUG("local_tenant_task mark continue is false"); + } // lock task ctx for update common::ObSpinLockGuard ctx_guard(ctx->lock_); ctx->last_modify_time_ = ObTimeUtility::current_time(); @@ -603,7 +608,10 @@ void OBTTLTimerPeriodicTask::runTimerTask() { int ret = OB_SUCCESS; ObCurTraceId::init(GCONF.self_addr_); - if (common::ObTTLUtil::check_can_do_work()) { + if (!ObKVFeatureModeUitl::is_ttl_enable()) { + // do nothing + LOG_DEBUG("ttl is disable"); + } else if (common::ObTTLUtil::check_can_do_work()) { if (OB_FAIL(tablet_ttl_mgr_.check_tenant_memory())) { LOG_WARN("fail to check all tenant memory", KR(ret)); } diff --git a/src/observer/table/ttl/ob_tenant_ttl_manager.cpp b/src/observer/table/ttl/ob_tenant_ttl_manager.cpp index 2c3ef5c78e..340b3d1f09 100644 --- a/src/observer/table/ttl/ob_tenant_ttl_manager.cpp +++ b/src/observer/table/ttl/ob_tenant_ttl_manager.cpp @@ -16,6 +16,7 @@ #include "share/ob_max_id_fetcher.h" #include "share/table/ob_ttl_util.h" #include "lib/oblog/ob_log_module.h" +#include "share/table/ob_table_config_util.h" using namespace oceanbase::share; using namespace oceanbase::common; @@ -30,7 +31,10 @@ void ObClearTTLHistoryTask::runTimerTask() { ObCurTraceId::init(GCONF.self_addr_); int ret = OB_SUCCESS; - if (IS_NOT_INIT) { + if (!ObKVFeatureModeUitl::is_ttl_enable()) { + // do nothing + LOG_DEBUG("ttl is disable"); + } else if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ob clear ttl history task is not init", KR(ret)); } else if (ObTTLUtil::check_can_do_work()) { @@ -581,7 +585,10 @@ void ObTTLTaskScheduler::runTimerTask() { int ret = OB_SUCCESS; ObCurTraceId::init(GCONF.self_addr_); - if (IS_NOT_INIT) { + if (!ObKVFeatureModeUitl::is_ttl_enable()) { + // do nothing + LOG_DEBUG("ttl is disable"); + } else if (IS_NOT_INIT) { ret = OB_NOT_INIT; LOG_WARN("ttl task mgr not init", KR(ret)); } else if (OB_FAIL(reload_tenant_task())) { diff --git a/src/share/CMakeLists.txt b/src/share/CMakeLists.txt index 41c4e3f068..a519fe3b85 100755 --- a/src/share/CMakeLists.txt +++ b/src/share/CMakeLists.txt @@ -261,6 +261,7 @@ ob_set_subtarget(ob_share common_mixed detect/ob_detect_manager_utils.cpp table/ob_table_load_sql_statistics.cpp table/ob_ttl_util.cpp + table/ob_table_config_util.cpp ) ob_set_subtarget(ob_share tablet diff --git a/src/share/config/ob_config.cpp b/src/share/config/ob_config.cpp index 558ba34870..7e05382abe 100644 --- a/src/share/config/ob_config.cpp +++ b/src/share/config/ob_config.cpp @@ -1110,6 +1110,43 @@ int ObConfigLogArchiveOptionsItem::format_option_str(const char *src, int64_t sr } return ret; } +ObConfigModeItem::ObConfigModeItem(ObConfigContainer *container, + Scope::ScopeInfo scope_info, + const char *name, + const char *def, + ObConfigParser* parser, + const char *info, + const ObParameterAttr attr) +:parser_(parser) +{ + MEMSET(value_, 0, MAX_MODE_BYTES); + if (OB_LIKELY(NULL != container)) { + container->set_refactored(ObConfigStringKey(name), this, 1); + } + init(scope_info, name, def, info, attr); +} + +ObConfigModeItem::~ObConfigModeItem() +{ + if (parser_ != NULL) { + delete parser_; + } +} + +bool ObConfigModeItem::set(const char *str) +{ + bool valid = false; + if (str == NULL || parser_ == NULL) { + valid = false; + OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "str or parser_ is NULL", K(str), K(parser_)); + } else { + valid = parser_->parse(str, value_, MAX_MODE_BYTES); + if (!valid) { + OB_LOG_RET(WARN, OB_ERR_UNEXPECTED, "parse config item fail", K(str), K(parser_)); + } + } + return valid; +} ObConfigVersionItem::ObConfigVersionItem(ObConfigContainer *container, Scope::ScopeInfo scope_info, diff --git a/src/share/config/ob_config.h b/src/share/config/ob_config.h index cb09d7190c..cea1dd29db 100644 --- a/src/share/config/ob_config.h +++ b/src/share/config/ob_config.h @@ -47,6 +47,7 @@ enum ObConfigItemType{ OB_CONF_ITEM_TYPE_CAPACITY = 9, OB_CONF_ITEM_TYPE_LOGARCHIVEOPT = 10, OB_CONF_ITEM_TYPE_VERSION = 11, + OB_CONF_ITEM_TYPE_MODE = 12, }; enum class ObConfigRangeOpts { @@ -1224,6 +1225,57 @@ private: common::ObSArray config_array_; }; +class ObConfigModeItem: public ObConfigItem +{ +public: + ObConfigModeItem(ObConfigContainer *container, + Scope::ScopeInfo scope_info, + const char *name, + const char *def, + ObConfigParser* parser, + const char *info, + const ObParameterAttr attr = ObParameterAttr()); + virtual ~ObConfigModeItem(); + // get_value() return the real-time value + const uint8_t* get_value() const { return value_; } + // get() return the real-time value if it does not need reboot, otherwise it return initial_value + const uint8_t* get() const { return value_; } + operator const uint8_t* () const { return value_; } + + virtual ObConfigItemType get_config_item_type() const { + return ObConfigItemType::OB_CONF_ITEM_TYPE_MODE; + } +protected: + //use current value to do input operation + bool set(const char *str); + const char *value_ptr() const override + { + return value_str_; + } + const char *value_reboot_ptr() const override + { + return value_reboot_str_; + } + uint64_t value_len() const override + { + return sizeof(value_str_); + } + uint64_t value_reboot_len() const override + { + return sizeof(value_reboot_str_); + } +protected: + static const uint64_t VALUE_BUF_SIZE = 65536UL; + static const int64_t MAX_MODE_BYTES = 32; + ObConfigParser *parser_; + char value_str_[VALUE_BUF_SIZE]; + char value_reboot_str_[VALUE_BUF_SIZE]; + // max bits size: 8 * 32 = 256 + uint8_t value_[MAX_MODE_BYTES]; +private: + DISALLOW_COPY_AND_ASSIGN(ObConfigModeItem); +}; + } // namespace common } // namespace oceanbase diff --git a/src/share/config/ob_config_helper.cpp b/src/share/config/ob_config_helper.cpp index 575c357bad..b0dfa1ab4c 100644 --- a/src/share/config/ob_config_helper.cpp +++ b/src/share/config/ob_config_helper.cpp @@ -29,7 +29,8 @@ #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" namespace oceanbase { using namespace share; @@ -875,5 +876,147 @@ bool ObConfigSQLTlsVersionChecker::check(const ObConfigItem &t) const 0 == tmp_str.case_compare("TLSV1.3"); } +int ObModeConfigParserUitl::parse_item_to_kv(char *item, ObString &key, ObString &value) +{ + 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, "=", &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(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> &kv_list) +{ + 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))) { + 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, 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; +} + } // end of namepace common } // end of namespace oceanbase diff --git a/src/share/config/ob_config_helper.h b/src/share/config/ob_config_helper.h index 0957224e12..7590cf726e 100644 --- a/src/share/config/ob_config_helper.h +++ b/src/share/config/ob_config_helper.h @@ -635,6 +635,40 @@ public: private: DISALLOW_COPY_AND_ASSIGN(ObConfigSQLTlsVersionChecker); }; + +class ObModeConfigParserUitl +{ +public: + // parse config item like: "xxx=yyy" + static int parse_item_to_kv(char *item, ObString &key, ObString &value); + static int get_kv_list(char *str, ObIArray> &kv_list); + // format str for split config item + static int format_mode_str(const char *src, int64_t src_len, char *dst, int64_t dst_len); +}; + +class ObConfigParser +{ +public: + ObConfigParser() {} + virtual ~ObConfigParser() {} + virtual bool parse(const char *str, uint8_t *arr, int64_t len) = 0; +private: + DISALLOW_COPY_AND_ASSIGN(ObConfigParser); +}; + +class ObKvFeatureModeParser : public ObConfigParser +{ +public: + ObKvFeatureModeParser() {} + virtual ~ObKvFeatureModeParser() {} + virtual bool parse(const char *str, uint8_t *arr, int64_t len) override; +public: + static const int8_t MODE_DEFAULT = 0b00; + static const int8_t MODE_ON = 0b01; + static const int8_t MODE_OFF = 0b10; + DISALLOW_COPY_AND_ASSIGN(ObKvFeatureModeParser); +}; + typedef __ObConfigContainer ObConfigContainer; } // namespace common diff --git a/src/share/config/ob_config_mode_name_def.h b/src/share/config/ob_config_mode_name_def.h new file mode 100644 index 0000000000..1f6dffeeeb --- /dev/null +++ b/src/share/config/ob_config_mode_name_def.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2023 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. + */ + +#ifndef OCEANBASE_SHARE_CONFIG_OB_CONFIG_MODE_NAME_DEF_H_ +#define OCEANBASE_SHARE_CONFIG_OB_CONFIG_MODE_NAME_DEF_H_ +// _obkv_feature_mode +#define MODE_NAME_TTL "ttl" +#define MODE_NAME_REROUTING "rerouting" +#define MODE_NAME_HOTKEY "hotkey" + +#define MODE_DEFAULT_VAL_TTL true +#define MODE_DEFAULT_VAL_REROUTING false +#define MODE_DEFAULT_VAL_HOTKEY false + +// mode value +#define MODE_VAL_ON "on" +#define MODE_VAL_OFF "off" + +#endif // diff --git a/src/share/parameter/ob_parameter_macro.h b/src/share/parameter/ob_parameter_macro.h index b353593f5d..f695f57b93 100644 --- a/src/share/parameter/ob_parameter_macro.h +++ b/src/share/parameter/ob_parameter_macro.h @@ -26,7 +26,8 @@ SCOPE(_DEF_PARAMETER_RANGE_EASY(access_specifier, param, _ ## SCOPE, name, args)) #define _DEF_PARAMETER_SCOPE_CHECKER_EASY(access_specifier, param, name, SCOPE, args...) \ SCOPE(_DEF_PARAMETER_CHECKER_EASY(access_specifier, param, _ ## SCOPE, name, args)) - +#define _DEF_PARAMETER_SCOPE_PARSER_EASY(access_specifier, param, name, SCOPE, args...) \ + SCOPE(_DEF_PARAMETER_PARSER_EASY(access_specifier, param, _ ## SCOPE, name, args)) #define _DEF_PARAMETER_SCOPE_IP_EASY(access_specifier, param, name, SCOPE, def, args...) \ SCOPE(_DEF_PARAMETER_CHECKER_EASY(access_specifier, param, _ ## SCOPE, name, def, \ common::ObConfigIpChecker, args)) @@ -94,6 +95,18 @@ access_specifier: } \ } name; +#define _DEF_PARAMETER_PARSER_EASY(access_specifier, param, scope, name, def, parser, args...) \ +access_specifier: \ + class ObConfig ## param ## Item ## _ ## name \ + : public common::ObConfig ## param ## Item \ + { \ + public: \ + ObConfig ## param ## Item ## _ ## name() \ + : common::ObConfig ## param ## Item( \ + local_container(), scope, #name, def, \ + new (std::nothrow) parser(), args) {} \ + } name; + //////////////////////////////////////////////////////////////////////////////// #define DEF_INT(args...) \ _DEF_PARAMETER_SCOPE_RANGE_EASY(public, Int, args) @@ -140,6 +153,9 @@ access_specifier: #define DEF_STR_LIST(args...) \ _DEF_PARAMETER_SCOPE_EASY(public, StrList, args) +#define DEF_MODE_WITH_PARSER(args...) \ + _DEF_PARAMETER_SCOPE_PARSER_EASY(public, Mode, args) + #define DEF_LOG_ARCHIVE_OPTIONS_WITH_CHECKER(args...) \ _DEF_PARAMETER_SCOPE_CHECKER_EASY(public, LogArchiveOptions, args) #define DEF_LOG_LEVEL(args...) \ diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index ebced62904..af556359e7 100755 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1628,3 +1628,7 @@ DEF_STR_WITH_CHECKER(sql_protocol_min_tls_version, OB_CLUSTER_PARAMETER, "none", "SQL SSL control options, used to specify the minimum SSL/TLS version number. " "values: none, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +// obkv +DEF_MODE_WITH_PARSER(_obkv_feature_mode, OB_CLUSTER_PARAMETER, "", common::ObKvFeatureModeParser, + "_obkv_feature_mode is a option list to control specified OBKV features on/off.", + ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); diff --git a/src/share/table/ob_table_config_util.cpp b/src/share/table/ob_table_config_util.cpp new file mode 100644 index 0000000000..01fad2d63d --- /dev/null +++ b/src/share/table/ob_table_config_util.cpp @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2023 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. + */ + +#define USING_LOG_PREFIX SHARE +#include "ob_table_config_util.h" +#include "lib/container/ob_se_array.h" +#include "share/config/ob_config_helper.h" +#include "share/config/ob_config_mode_name_def.h" +namespace oceanbase +{ +namespace common +{ +ObKVFeatureMode::ObKVFeatureMode(const uint8_t *values) +{ + if (OB_UNLIKELY(values == NULL)) { + value_ = 0; + is_valid_ = false; + } else { + value_ = values[0]; + is_valid_ = true; + } +} + +void ObKVFeatureMode::set_ttl_mode(uint8_t mode) +{ + is_valid_ = check_mode_valid(mode); + if (is_valid_) { + ttl_mode_ = mode; + } +} + +void ObKVFeatureMode::set_rerouting_mode(uint8_t mode) +{ + is_valid_ = check_mode_valid(mode); + if (is_valid_) { + rerouting_mode_ = mode; + } +} + +void ObKVFeatureMode::set_hotkey_mode(uint8_t mode) +{ + is_valid_ = check_mode_valid(mode); + if (is_valid_) { + hotkey_mode_ = mode; + } +} + +void ObKVFeatureMode::set_value(uint8_t value) +{ + if ((value & 0b11) == 0b11 || ((value >> 2) & 0b11) == 0b11 || ((value >> 4) & 0b11) == 0b11) { + is_valid_ = false; + } else { + is_valid_ = true; + value_ = value; + } +} + + +bool ObKVFeatureMode::is_ttl_enable() { + bool mode = MODE_DEFAULT_VAL_TTL; + if (ttl_mode_ == ObKvFeatureModeParser::MODE_ON) { + mode = true; + } else if (ttl_mode_ == ObKvFeatureModeParser::MODE_OFF) { + mode = false; + } + return mode; +} + +bool ObKVFeatureMode::is_rerouting_enable() { + bool mode = MODE_DEFAULT_VAL_REROUTING; + if (rerouting_mode_ == ObKvFeatureModeParser::MODE_ON) { + mode = true; + } else if (rerouting_mode_ == ObKvFeatureModeParser::MODE_ON) { + mode = false; + } + return mode; +} + +bool ObKVFeatureMode::is_hotkey_enable() { + bool mode = MODE_DEFAULT_VAL_HOTKEY; + if (hotkey_mode_ == ObKvFeatureModeParser::MODE_ON) { + mode = true; + } else if (hotkey_mode_ == ObKvFeatureModeParser::MODE_ON) { + mode = false; + } + return mode; +} + +bool ObKVFeatureModeUitl::is_obkv_feature_enable(ObKVFeatureType feat_type) +{ + bool bret = false; + ObKVFeatureMode cfg(GCONF._obkv_feature_mode); + if (!cfg.is_valid()) { + bret = false; + OB_LOG_RET(WARN, OB_INVALID_ARGUMENT, "unexpected, cfg is invalid"); + } else { + switch (feat_type) { + case ObKVFeatureType::TTL: + bret = cfg.is_ttl_enable(); + break; + case ObKVFeatureType::REROUTING: + bret = cfg.is_rerouting_enable(); + break; + case ObKVFeatureType::HOTKEY: + bret = cfg.is_hotkey_enable(); + break; + default: + OB_LOG_RET(WARN, OB_INVALID_ARGUMENT, "unexpected feature type", K(feat_type)); + break; + } + } + return bret; +} + +bool ObKVFeatureModeUitl::is_ttl_enable() +{ + return is_obkv_feature_enable(ObKVFeatureType::TTL); +} + +bool ObKVFeatureModeUitl::is_rerouting_enable() +{ + return is_obkv_feature_enable(ObKVFeatureType::REROUTING); +} + +bool ObKVFeatureModeUitl::is_hotkey_enable() +{ + return is_obkv_feature_enable(ObKVFeatureType::HOTKEY); +} + +} +} \ No newline at end of file diff --git a/src/share/table/ob_table_config_util.h b/src/share/table/ob_table_config_util.h new file mode 100644 index 0000000000..a41aec3c8f --- /dev/null +++ b/src/share/table/ob_table_config_util.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2023 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. + */ + +#ifndef OCEANBASE_OB_TABLE_CONFIG_UTIL_H_ +#define OCEANBASE_OB_TABLE_CONFIG_UTIL_H_ +#include "lib/utility/ob_macro_utils.h" +#include "lib/utility/ob_print_utils.h" +#include "share/config/ob_server_config.h" +namespace oceanbase +{ +namespace common +{ +enum ObKVFeatureType { + INVALIDTYPE, + TTL, + REROUTING, + HOTKEY, + MAXTYPE +}; + +class ObKVFeatureMode final +{ +public: + ObKVFeatureMode(): is_valid_(false), value_(0) {} + ObKVFeatureMode(const uint8_t *values); + bool is_valid() { return is_valid_; } + bool check_mode_valid(uint8_t mode) { return mode > 2 ? false : true; } + bool is_ttl_enable(); + bool is_rerouting_enable(); + bool is_hotkey_enable(); + void set_ttl_mode(uint8_t mode); + void set_rerouting_mode(uint8_t mode); + void set_hotkey_mode(uint8_t mode); + void set_value(uint8_t value); + int8_t get_value() const { return value_; } +private: + bool is_valid_; + union { + uint8_t value_; + struct { + uint8_t ttl_mode_ : 2; + uint8_t rerouting_mode_ : 2; + uint8_t hotkey_mode_ : 2; + uint8_t reserver_mode_ :2; + }; + }; +private: + DISALLOW_COPY_AND_ASSIGN(ObKVFeatureMode); +}; + +class ObKVFeatureModeUitl +{ +public: + static bool is_obkv_feature_enable(ObKVFeatureType feat_type); + static bool is_ttl_enable(); + static bool is_rerouting_enable(); + static bool is_hotkey_enable(); +}; + +} +} +#endif \ No newline at end of file diff --git a/src/sql/resolver/cmd/ob_alter_system_resolver.cpp b/src/sql/resolver/cmd/ob_alter_system_resolver.cpp index 101823bd93..b1bee17192 100644 --- a/src/sql/resolver/cmd/ob_alter_system_resolver.cpp +++ b/src/sql/resolver/cmd/ob_alter_system_resolver.cpp @@ -44,6 +44,7 @@ #include "observer/mysql/ob_query_response_time.h" #include "rootserver/ob_rs_job_table_operator.h" //ObRsJobType #include "sql/resolver/cmd/ob_kill_stmt.h" +#include "share/table/ob_table_config_util.h" namespace oceanbase { @@ -4327,6 +4328,10 @@ int ObTableTTLResolver::resolve(const ParseNode& parse_tree) ret = OB_NOT_SUPPORTED; LOG_WARN("TTL command is not supported in data version less than 4.2.1", K(ret), K(tenant_data_version)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "TTL command is not supported in data version less than 4.2.1"); + } else if (!ObKVFeatureModeUitl::is_ttl_enable()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("ttl is disable", K(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "ttl is disable, set by config item _obkv_feature_mode"); } else if (OB_UNLIKELY(T_TABLE_TTL != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_TABLE_TTL", "type", get_type_name(parse_tree.type_)); diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result index 6af8b45257..108c5bb4dc 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result @@ -316,6 +316,7 @@ _minor_compaction_amplification_factor _min_malloc_sample_interval _mvcc_gc_using_min_txn_snapshot _nested_loop_join_enabled +_obkv_feature_mode _ob_ddl_timeout _ob_elr_fast_freeze_threshold _ob_enable_direct_load diff --git a/unittest/observer/CMakeLists.txt b/unittest/observer/CMakeLists.txt index 39ff2f2303..fc0e64f742 100644 --- a/unittest/observer/CMakeLists.txt +++ b/unittest/observer/CMakeLists.txt @@ -5,6 +5,7 @@ storage_unittest(test_create_executor table/test_create_executor.cpp) storage_unittest(test_table_aggregation table/test_table_aggregation.cpp) storage_unittest(test_table_sess_pool table/test_table_sess_pool.cpp) storage_unittest(test_ingress_bw_alloc_manager net/test_ingress_bw_alloc_manager.cpp) +ob_unittest(test_obkv_config tableapi/test_obkv_config.cpp) ob_unittest(test_uniq_task_queue) add_subdirectory(rpc EXCLUDE_FROM_ALL) diff --git a/unittest/observer/tableapi/test_obkv_config.cpp b/unittest/observer/tableapi/test_obkv_config.cpp new file mode 100644 index 0000000000..d36df7bfd8 --- /dev/null +++ b/unittest/observer/tableapi/test_obkv_config.cpp @@ -0,0 +1,156 @@ +#include "share/table/ob_table_config_util.h" +#include "lib/time/ob_time_utility.h" +#include "share/parameter/ob_parameter_macro.h" +#include + +namespace oceanbase +{ +using namespace share; +namespace common +{ +ObConfigContainer l_container; +static ObConfigContainer *local_container() +{ + return &l_container; +} +class TestObKvConfig : public ::testing::Test +{ +public: +#undef OB_CLUSTER_PARAMETER +#define OB_CLUSTER_PARAMETER(args...) args +DEF_MODE_WITH_PARSER(_obkv_feature_mode, OB_CLUSTER_PARAMETER, "", common::ObKvFeatureModeParser, + "_obkv_feature_mode is a option list to control specified OBKV features on/off.", + ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +#undef OB_CLUSTER_PARAMETER +}; + +TEST_F(TestObKvConfig, test_process_item) +{ + ObString key; + ObString value; + char str1[100] = {"ttl=off"}; + ASSERT_EQ(OB_SUCCESS, ObModeConfigParserUitl::parse_item_to_kv(str1, key, value)); + ASSERT_EQ(key, ObString("ttl")); + ASSERT_EQ(value, ObString("off")); + + char str2[100] = {" ttl = off "}; + ASSERT_EQ(OB_SUCCESS, ObModeConfigParserUitl::parse_item_to_kv(str2, key, value)); + ASSERT_EQ(key, ObString("ttl")); + ASSERT_EQ(value, ObString("off")); + + char str3[100] = {" rerouting =off "}; + ASSERT_EQ(OB_SUCCESS, ObModeConfigParserUitl::parse_item_to_kv(str3, key, value)); + ASSERT_EQ(key, ObString("rerouting")); + ASSERT_EQ(value, ObString("off")); + + char str4[100] = {"ttl=on, rerouting=off"}; + common::ObSEArray, 8> kv_list; + ASSERT_EQ(OB_SUCCESS, ObModeConfigParserUitl::get_kv_list(str4, kv_list)); + ASSERT_EQ(2, kv_list.count()); + ASSERT_EQ(kv_list.at(0).first, ObString("ttl")); + ASSERT_EQ(kv_list.at(0).second, ObString("on")); + ASSERT_EQ(kv_list.at(1).first, ObString("rerouting")); + ASSERT_EQ(kv_list.at(1).second, ObString("off")); +} + + +TEST_F(TestObKvConfig, test_parse) +{ + ObKvFeatureModeParser parser; + uint8_t arr[32]; + ASSERT_EQ(true, parser.parse("ttl=on, rerouting=off", arr, 32)); + ASSERT_EQ(arr[0], 0b00001001); + + MEMSET(arr, 0, 32); + ASSERT_EQ(true, parser.parse("ttl=on, ttl=off, rerouting=on", arr, 32)); + ASSERT_EQ(arr[0], 0b0000110); + + MEMSET(arr, 0, 32); + ASSERT_EQ(true, parser.parse("ttl=on, ttl=off", arr, 32)); + ASSERT_EQ(arr[0], 0b00000010); + + MEMSET(arr, 0, 32); + ASSERT_EQ(true, parser.parse("ttl=on, hotkey=on, rerouting=on", arr, 32)); + ASSERT_EQ(arr[0], 0b00010101); + + MEMSET(arr, 0, 32); + ASSERT_EQ(false, parser.parse("ttl=on, ttt=off", arr, 32)); + + MEMSET(arr, 0, 32); + ASSERT_EQ(false, parser.parse("ttl=on, rerouting=default", arr, 32)); + + MEMSET(arr, 0, 32); + ASSERT_EQ(true, parser.parse("", arr, 32)); + ASSERT_EQ(arr[0], 0); + + MEMSET(arr, 0, 32); + ASSERT_EQ(false, parser.parse("ttl=on, ttt=off, ", arr, 32)); + + MEMSET(arr, 0, 32); + ASSERT_EQ(false, parser.parse("ttl=on, ttt=off,", arr, 32)); +} + +TEST_F(TestObKvConfig, test_obkv_feature_mode) +{ + const uint8_t *value = _obkv_feature_mode; + ASSERT_NE((void*)NULL, (void*)value); + ASSERT_EQ(value[0], 0); + ASSERT_EQ(true, _obkv_feature_mode.set_value("ttl=off, rerouting=on, hotkey=on")); + const uint8_t *value1 = _obkv_feature_mode.get(); + ASSERT_NE((void*)NULL, (void*)value1); + ASSERT_EQ(value1[0], 0b00010110); + // bad case + ASSERT_EQ(false, _obkv_feature_mode.set_value("hotkey=off=")); + ASSERT_EQ(false, _obkv_feature_mode.set_value("=off")); + ASSERT_EQ(false, _obkv_feature_mode.set_value(",")); + ASSERT_EQ(false, _obkv_feature_mode.set_value(" , ")); + ASSERT_EQ(false, _obkv_feature_mode.set_value(" ,hotkey=off")); + ASSERT_EQ(false, _obkv_feature_mode.set_value(",hotkey=off")); + ASSERT_EQ(false, _obkv_feature_mode.set_value("ttl=off,, hotkey=off")); + ASSERT_EQ(false, _obkv_feature_mode.set_value("ttl=off, , hotkey=off")); + ASSERT_EQ(false, _obkv_feature_mode.set_value("ttl=off, rerouting=on, ")); + ASSERT_EQ(false, _obkv_feature_mode.set_value("ttl=off, rerouting=on,")); +} + +TEST_F(TestObKvConfig, testObKVFeatureMode) +{ + // rerouting=off, ttl=on + uint8_t values[1] = {0b001001}; + ObKVFeatureMode kv_mode(values); + ASSERT_EQ(true, kv_mode.is_ttl_enable()); + ASSERT_EQ(false, kv_mode.is_rerouting_enable()); + // default + ObKVFeatureMode kv_mode_1; + ASSERT_EQ(false, kv_mode_1.is_valid()); + kv_mode_1.set_ttl_mode(0b10); + kv_mode_1.set_rerouting_mode(0b01); + kv_mode_1.set_hotkey_mode(0b01); + ASSERT_EQ(true, kv_mode_1.is_valid()); + ASSERT_EQ(false, kv_mode_1.is_ttl_enable()); + ASSERT_EQ(true, kv_mode_1.is_rerouting_enable()); + ASSERT_EQ(true, kv_mode_1.is_hotkey_enable()); + kv_mode_1.set_value(0b11101001); + ASSERT_EQ(true, kv_mode_1.is_valid()); + ASSERT_EQ(true, kv_mode_1.is_ttl_enable()); + ASSERT_EQ(false, kv_mode_1.is_rerouting_enable()); + ASSERT_EQ(false, kv_mode_1.is_hotkey_enable()); + // bad case + kv_mode_1.set_ttl_mode(0b11); + ASSERT_EQ(false, kv_mode_1.is_valid()); + kv_mode_1.set_hotkey_mode(0b11); + ASSERT_EQ(false, kv_mode_1.is_valid()); + kv_mode_1.set_rerouting_mode(0b11); + ASSERT_EQ(false, kv_mode_1.is_valid()); + kv_mode_1.set_value(0b00111111); + ASSERT_EQ(false, kv_mode_1.is_valid()); +} + +} +} + +int main(int argc, char **argv) +{ + oceanbase::common::ObLogger::get_logger().set_log_level("INFO"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file