1223 lines
45 KiB
C++
1223 lines
45 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.
|
|
*/
|
|
|
|
#define USING_LOG_PREFIX SHARE
|
|
|
|
#include "share/ob_web_service_root_addr.h"
|
|
#include <curl/curl.h>
|
|
#include "lib/json/ob_json.h"
|
|
#include "lib/string/ob_sql_string.h"
|
|
#include "share/config/ob_server_config.h"
|
|
#include "observer/ob_server_struct.h"
|
|
#include "share/ob_cluster_version.h"
|
|
#include "share/ob_rpc_struct.h"
|
|
#include "share/ob_inner_config_root_addr.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace common;
|
|
|
|
namespace share
|
|
{
|
|
void ObClusterRsAddr::reset()
|
|
{
|
|
cluster_id_ = OB_INVALID_ID;
|
|
addr_.reset();
|
|
}
|
|
|
|
bool ObClusterRsAddr::is_valid() const
|
|
{
|
|
return cluster_id_ > 0 && addr_.is_valid();
|
|
}
|
|
|
|
int ObClusterRsAddr::assign(const ObClusterRsAddr &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (this != &other) {
|
|
cluster_id_ = other.cluster_id_;
|
|
addr_ = other.addr_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObClusterAddr::reset()
|
|
{
|
|
cluster_id_ = common::OB_INVALID_ID;
|
|
cluster_role_ = INVALID_CLUSTER_ROLE;
|
|
cluster_status_ = INVALID_CLUSTER_STATUS;
|
|
timestamp_ = 0;
|
|
cluster_name_.reset();
|
|
addr_list_.reuse();
|
|
readonly_addr_list_.reuse();
|
|
cluster_idx_ = common::OB_INVALID_INDEX;
|
|
current_scn_ = OB_INVALID_VERSION;
|
|
redo_transport_options_.reset();
|
|
protection_level_ = common::MAXIMUM_PERFORMANCE_LEVEL;
|
|
sync_status_ = NOT_AVAILABLE;
|
|
last_hb_ts_ = common::OB_INVALID_TIMESTAMP;
|
|
}
|
|
|
|
bool ObClusterAddr::is_valid() const
|
|
{
|
|
bool bret = true;
|
|
if (OB_INVALID_ID == cluster_id_
|
|
|| INVALID_CLUSTER_ROLE == cluster_role_
|
|
|| 0 == cluster_name_.size()) {
|
|
bret = false;
|
|
}
|
|
return bret;
|
|
}
|
|
int ObClusterAddr::assign(const ObClusterAddr &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(addr_list_.assign(other.addr_list_))) {
|
|
LOG_WARN("failed to assign addr list", K(ret), K(other));
|
|
} else if (OB_FAIL(readonly_addr_list_.assign(other.readonly_addr_list_))) {
|
|
LOG_WARN("failed to assign addr list", K(ret), K(other));
|
|
} else if (OB_FAIL(cluster_name_.assign(other.cluster_name_))) {
|
|
LOG_WARN("fail to assign", KR(ret), K(other));
|
|
} else {
|
|
cluster_id_ = other.cluster_id_;
|
|
cluster_idx_ = other.cluster_idx_;
|
|
cluster_role_ = other.cluster_role_;
|
|
cluster_status_ = other.cluster_status_;
|
|
current_scn_ = other.current_scn_;
|
|
redo_transport_options_ = other.redo_transport_options_;
|
|
protection_level_ = other.protection_level_;
|
|
sync_status_ = other.sync_status_;
|
|
last_hb_ts_ = other.last_hb_ts_;
|
|
timestamp_ = other.timestamp_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObClusterAddr::operator==(const ObClusterAddr &other) const
|
|
{
|
|
bool b_ret = false;
|
|
if (this == &other) {
|
|
b_ret = true;
|
|
} else if (addr_list_.count() != other.addr_list_.count()
|
|
|| readonly_addr_list_.count() != other.readonly_addr_list_.count()
|
|
|| cluster_id_ != other.cluster_id_
|
|
|| cluster_idx_ != other.cluster_idx_
|
|
|| cluster_role_ != other.cluster_role_
|
|
|| cluster_status_ != other.cluster_status_
|
|
|| cluster_name_ != other.cluster_name_
|
|
|| current_scn_ != other.current_scn_
|
|
|| timestamp_ != other.timestamp_
|
|
|| redo_transport_options_ != other.redo_transport_options_
|
|
|| protection_level_ != other.protection_level_) {
|
|
b_ret = false;
|
|
} else {
|
|
b_ret = true;
|
|
for (int64_t i = 0; b_ret && i < other.addr_list_.count(); ++i) {
|
|
if (addr_list_.at(i) == other.addr_list_.at(i)) {
|
|
continue;
|
|
} else {
|
|
b_ret = false;
|
|
}
|
|
}
|
|
for (int64_t i = 0; b_ret && i < other.readonly_addr_list_.count(); ++i) {
|
|
if (readonly_addr_list_.at(i) == other.readonly_addr_list_.at(i)) {
|
|
continue;
|
|
} else {
|
|
b_ret = false;
|
|
}
|
|
}
|
|
}
|
|
if (!b_ret) {
|
|
LOG_INFO("not equal", K(b_ret), "this", *this, K(other));
|
|
}
|
|
return b_ret;
|
|
}
|
|
int ObClusterAddr::append_redo_transport_options_change(
|
|
common::ObString &redo_transport_options,
|
|
common::ObIAllocator &alloc) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSqlString str;
|
|
|
|
if (OB_FAIL(redo_transport_options_.get_redo_transport_options_str(str))) {
|
|
LOG_WARN("fail to redo_transport_options", KR(ret), K(redo_transport_options_));
|
|
} else if (OB_FAIL(ob_write_string(alloc, str.string(), redo_transport_options))) {
|
|
LOG_WARN("failed to write stirng", KR(ret), K(str));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObClusterAddr::construct_rootservice_list(
|
|
common::ObString &rootservice_list,
|
|
common::ObIAllocator &alloc) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSqlString str;
|
|
|
|
if (OB_FAIL(ObInnerConfigRootAddr::format_rootservice_list(addr_list_, str))) {
|
|
LOG_WARN("fail to format rootservice list", KR(ret), K(addr_list_));
|
|
} else if (str.length() <= 0) {
|
|
rootservice_list.reset();
|
|
LOG_INFO("cluster rootservice list is empty", K(addr_list_), K(str));
|
|
} else if (OB_FAIL(ob_write_string(alloc, str.string(), rootservice_list))) {
|
|
LOG_WARN("failed to write stirng", KR(ret), K(str));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
OB_SERIALIZE_MEMBER(ObClusterAddr, cluster_id_, cluster_role_, addr_list_,
|
|
readonly_addr_list_, timestamp_, cluster_name_, cluster_idx_,
|
|
cluster_status_, current_scn_, redo_transport_options_, protection_level_,
|
|
sync_status_, last_hb_ts_);
|
|
|
|
int ObWebServiceRootAddr::build_new_config_url(char* buf, const int64_t buf_len,
|
|
const char* config_url, const int64_t cluster_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(buf) || OB_ISNULL(config_url) || INVALID_CLUSTER_ID == cluster_id) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(buf), K(config_url), K(cluster_id));
|
|
} else {
|
|
int64_t pos = 0;
|
|
//compatible with obtest and configserver
|
|
//it can remove after upgrade obtest
|
|
ObString tmp_url(strlen(config_url), config_url);
|
|
if (OB_ISNULL(tmp_url.find('?'))) {
|
|
BUF_PRINTF("%s?%s=2&%s=%ld", config_url, JSON_VERSION, JSON_OB_CLUSTER_ID, cluster_id);
|
|
} else {
|
|
BUF_PRINTF("%s&%s=2&%s=%ld", config_url, JSON_VERSION, JSON_OB_CLUSTER_ID, cluster_id);
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
LOG_WARN("fail to print buf", K(ret), K(config_url));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::store(const ObIAddrList &addr_list, const ObIAddrList &readonly_addr_list,
|
|
const bool force, const common::ObClusterRole cluster_role,
|
|
const int64_t timestamp)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(force); //always update web config
|
|
if (OB_FAIL(check_inner_stat())) {
|
|
LOG_WARN("fail to check inner stat", KR(ret));
|
|
} else if (addr_list.empty()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), "addr count", addr_list.count());
|
|
} else {
|
|
const char *url = config_->obconfig_url.str();
|
|
const char *appname = config_->cluster.str();
|
|
const int64_t cluster_id = config_->cluster_id;
|
|
//default 4s
|
|
const int64_t timeout_ms = config_->rpc_timeout / 1000 + 2 * 1000;
|
|
const int64_t max_config_length = OB_MAX_CONFIG_URL_LENGTH;
|
|
char new_config_url[max_config_length] = {'\0'};
|
|
if (NULL == url || NULL == appname || cluster_id <= 0 || timeout_ms <= 0) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("NULL url or NULL appname or invalid timeout",
|
|
K(ret), KP(url), KP(appname), K(cluster_id), K(timeout_ms));
|
|
} else if (OB_FAIL(build_new_config_url(new_config_url, max_config_length, url, cluster_id))) {
|
|
LOG_WARN("fail to build new config url", K(ret), K(cluster_id), K(url));
|
|
} else if (OB_FAIL(store_rs_list_on_url(addr_list, readonly_addr_list, appname, cluster_id,
|
|
cluster_role, new_config_url, timeout_ms,
|
|
timestamp))) {
|
|
LOG_WARN("store_rs_list_on_url fail",
|
|
K(ret), K(addr_list), K(readonly_addr_list), K(appname),
|
|
K(new_config_url), K(timeout_ms),
|
|
K(timestamp));
|
|
} else {
|
|
LOG_INFO("store_rs_list_on_url success", K(ret), K(addr_list), K(cluster_role),
|
|
K(readonly_addr_list), K(appname), K(new_config_url), K(timeout_ms));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObWebServiceRootAddr::fetch(
|
|
ObIAddrList &addr_list,
|
|
ObIAddrList &readonly_addr_list)
|
|
{
|
|
int ret = OB_NOT_SUPPORTED;
|
|
UNUSEDx(addr_list, readonly_addr_list);
|
|
LOG_WARN("observer can not fetch rs list from configserver", KR(ret));
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::store_rs_list_on_url(
|
|
const ObIAddrList &rs_list,
|
|
const ObIAddrList &readonly_rs_list,
|
|
const char *appname,
|
|
const int64_t cluster_id,
|
|
const common::ObClusterRole cluster_role,
|
|
const char *url,
|
|
const int64_t timeout_ms,
|
|
const int64_t timestamp)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSqlString json;
|
|
ObSqlString content;
|
|
if (rs_list.count() <= 0 || NULL == url || NULL == appname
|
|
|| cluster_id <= 0 || timeout_ms <= 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid arguments", K(ret),
|
|
"addr_count", rs_list.count(), KP(url), KP(appname), K(cluster_id), K(timeout_ms));
|
|
} else if (OB_FAIL(to_json(rs_list, readonly_rs_list, appname,
|
|
cluster_id, cluster_role, timestamp, json))) {
|
|
LOG_WARN("convert addr list to json format failed", K(ret), K(rs_list), K(readonly_rs_list), K(appname));
|
|
} else if (OB_FAIL(call_service(json.ptr(), content, url, timeout_ms))) {
|
|
LOG_WARN("call web service failed", K(ret), K(json), K(url), K(timeout_ms));
|
|
} else if (OB_FAIL(check_store_result(content))) {
|
|
LOG_WARN("fail to check result", K(ret), K(content), K(url));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::check_store_result(const ObSqlString &content)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArenaAllocator allocator(ObModIds::OB_JSON_PARSER);
|
|
json::Parser parser;
|
|
json::Value *root = NULL;
|
|
if (OB_FAIL(parser.init(&allocator))) {
|
|
LOG_WARN("json parser init failed", K(ret));
|
|
} else if (OB_ISNULL(content.ptr()) || content.empty()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get invalid content", K(ret), K(content));
|
|
} else if (OB_FAIL(parser.parse(content.ptr(), strlen(content.ptr()), root))) {
|
|
LOG_WARN("parse json failed", K(ret), K(content));
|
|
} else if (OB_ISNULL(root)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("no root value", K(ret));
|
|
} else if (json::JT_OBJECT != root->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("error json format", K(ret), K(content), "root", *root);
|
|
} else {
|
|
bool find_code = false;
|
|
DLIST_FOREACH(it, root->get_object()) {
|
|
if (it->name_.case_compare(JSON_RES_CODE) == 0) {
|
|
find_code = true;
|
|
if (NULL == it->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_NUMBER != it->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected code type", K(ret), "type", it->value_->get_type());
|
|
} else {
|
|
const int64_t code = it->value_->get_number();
|
|
if (2018 == code) {
|
|
ret = OB_OBCONFIG_CLUSTER_NOT_EXIST;
|
|
LOG_WARN("cluster not exist", K(ret), K(code));
|
|
} else if (200 != code) {
|
|
ret = OB_OBCONFIG_RETURN_ERROR;
|
|
LOG_WARN("return code not success", K(ret), K(code));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !find_code) {
|
|
ret = OB_OBCONFIG_RETURN_ERROR;
|
|
LOG_WARN("fail to find response code", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::fetch_rs_list_from_url(
|
|
const char *appname,
|
|
const char *url,
|
|
const int64_t timeout_ms,
|
|
ObIAddrList &rs_list,
|
|
ObIAddrList &readonly_rs_list,
|
|
ObClusterRole &cluster_role)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSqlString json;
|
|
ObClusterAddr cluster;
|
|
|
|
// appname can be NULL to ignore appname check
|
|
if (NULL == url || timeout_ms <= 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid arguments", K(ret), KP(url), K(timeout_ms));
|
|
} else if (OB_FAIL(call_service(NULL, json, url, timeout_ms))) {
|
|
LOG_WARN("call web service failed", K(ret), K(url), K(timeout_ms));
|
|
} else if (json.empty()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("web service returned empty result", K(ret));
|
|
} else if (OB_FAIL(from_json(json.ptr(), appname, cluster))) {
|
|
LOG_WARN("convert json to rootserver address list failed",
|
|
K(ret), K(json), K(appname));
|
|
} else if (OB_FAIL(rs_list.assign(cluster.addr_list_))) {
|
|
LOG_WARN("fail to assign", KR(ret));
|
|
} else if (OB_FAIL(readonly_rs_list.assign(cluster.readonly_addr_list_))) {
|
|
LOG_WARN("fail to assign", KR(ret));
|
|
} else {
|
|
cluster_role = cluster.cluster_role_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// json format:
|
|
//
|
|
// { "rs_list" :
|
|
// [ {
|
|
// "address" : "ip:port",
|
|
// "role" : "leader",
|
|
// "sql_port" : 3306
|
|
// },
|
|
// {
|
|
// "address" : "ip:port",
|
|
// "role" : "follower",
|
|
// "sql_port" : 3306
|
|
// },
|
|
// {
|
|
// "address" : "ip:port",
|
|
// "role" : "follower",
|
|
// "sql_port" : 3306
|
|
// }
|
|
// ],
|
|
// "readonly_rs_list" :
|
|
// [ {
|
|
// "address" : "ip:port",
|
|
// "role" : "follower",
|
|
// "sql_port" : 3306
|
|
// },
|
|
// {
|
|
// "address" : "ip:port",
|
|
// "role" : "follower",
|
|
// "sql_port" : 3306
|
|
// },
|
|
// {
|
|
// "address" : "ip:port",
|
|
// "role" : "follower",
|
|
// "sql_port" : 3306
|
|
// }
|
|
// ]
|
|
// }
|
|
//
|
|
int ObWebServiceRootAddr::parse_data(const json::Value *data,
|
|
ObClusterAddr &cluster)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
json::Value *rs_list = NULL;
|
|
json::Value *readonly_rs_list = NULL;
|
|
cluster.reset();
|
|
if (NULL == data) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("no data filed found", K(ret));
|
|
} else if (json::JT_OBJECT != data->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("data filed not object", K(ret), "data", *data);
|
|
} else {
|
|
DLIST_FOREACH(it, data->get_object()) {
|
|
if (0 == it->name_.case_compare(JSON_RS_LIST)) {
|
|
rs_list = it->value_;
|
|
} else if (0 == it->name_.case_compare(JSON_READONLY_RS_LIST)) {
|
|
readonly_rs_list = it->value_;
|
|
} else if (0 == it->name_.case_compare(JSON_TYPE)) {
|
|
if (OB_ISNULL(it->value_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_STRING != it->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected cluster type", K(ret), "type", it->value_->get_type());
|
|
} else if (it->value_->get_string().case_compare(JSON_PRIMARY) == 0) {
|
|
cluster.cluster_role_ = PRIMARY_CLUSTER;
|
|
} else if (it->value_->get_string().case_compare(JSON_STANDBY) == 0) {
|
|
cluster.cluster_role_ = STANDBY_CLUSTER;
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid cluster type", K(ret), "type", it->value_->get_string());
|
|
}
|
|
} else if (it->name_.case_compare(JSON_OB_REGION_ID) == 0
|
|
|| it->name_.case_compare(JSON_OB_CLUSTER_ID) == 0) {
|
|
if (NULL == it->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_NUMBER != it->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected cluster_id type", K(ret), "type", it->value_->get_type());
|
|
} else {
|
|
cluster.cluster_id_ = it->value_->get_number();
|
|
}
|
|
} else if (it->name_.case_compare(JSON_TIMESTAMP) == 0) {
|
|
if (NULL == it->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_NUMBER != it->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected cluster_id type", K(ret), "type", it->value_->get_type());
|
|
} else {
|
|
cluster.timestamp_ = it->value_->get_number();
|
|
}
|
|
} else if (0 == it->name_.case_compare(JSON_OB_REGION)
|
|
|| 0 == it->name_.case_compare(JSON_OB_CLUSTER)) {
|
|
if (NULL == it->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_STRING != it->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected obregion type", K(ret), "type", it->value_->get_type());
|
|
} else if (OB_FAIL(cluster.cluster_name_.assign(it->value_->get_string()))) {
|
|
LOG_WARN("fail to assign string", KR(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (NULL == rs_list) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("no rs list found in json", K(ret));
|
|
} else if (OB_FAIL(get_addr_list(rs_list, cluster.addr_list_))) {
|
|
LOG_WARN("fail to parse rs_list", K(ret), "rs_list", *rs_list);
|
|
} else if (NULL == readonly_rs_list) {
|
|
// readonly_rs_list is allowed to be null
|
|
LOG_WARN("no readonly rs list found in json", K(ret));
|
|
} else if (OB_FAIL(get_addr_list(readonly_rs_list, cluster.readonly_addr_list_))) {
|
|
LOG_WARN("fail to parse readonly_rs_list", K(ret), "readonly_rs_list", *readonly_rs_list);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::from_json(
|
|
const char *json_str,
|
|
const char *appname,
|
|
ObClusterAddr &cluster)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
cluster.reset();
|
|
ObArenaAllocator allocator(ObModIds::OB_JSON_PARSER);
|
|
json::Parser parser;
|
|
json::Value *root = NULL;
|
|
// appname can be NULL to ignore appname check
|
|
if (NULL == json_str) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), KP(json_str));
|
|
} else if (OB_FAIL(parser.init(&allocator))) {
|
|
LOG_WARN("json parser init failed", K(ret));
|
|
} else if (OB_FAIL(parser.parse(json_str, strlen(json_str), root))) {
|
|
LOG_WARN("parse json failed", K(ret), K(json_str));
|
|
} else if (NULL == root) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("no root value", K(ret));
|
|
} else {
|
|
json::Value *data = NULL;
|
|
// check return code and get data filed
|
|
if (json::JT_OBJECT != root->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("error json format", K(ret), K(json_str), "root", *root);
|
|
} else {
|
|
DLIST_FOREACH(it, root->get_object()) {
|
|
if (it->name_.case_compare(JSON_RES_DATA) == 0) {
|
|
data = it->value_;
|
|
}
|
|
if (it->name_.case_compare(JSON_RES_CODE) == 0) {
|
|
if (NULL == it->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_NUMBER != it->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected code type", K(ret), "type", it->value_->get_type());
|
|
} else {
|
|
const int64_t code = it->value_->get_number();
|
|
if (200 != code) {
|
|
ret = OB_OBCONFIG_RETURN_ERROR;
|
|
LOG_WARN("return code not success", K(ret), K(code));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(data)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("no data filed found", K(ret));
|
|
} else if (OB_FAIL(parse_data(data, cluster))) {
|
|
LOG_WARN("fail to parse data", KR(ret));
|
|
} else if (NULL != appname && cluster.cluster_name_.str().case_compare(appname) != 0) {
|
|
ret = OB_OBCONFIG_APPNAME_MISMATCH;
|
|
LOG_ERROR("obconfig appname mismatch",
|
|
K(ret), K(appname), "obregion", cluster.cluster_name_);
|
|
}
|
|
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::get_addr_list(json::Value *&rs_list, ObIAddrList &addr_list)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
addr_list.reuse();
|
|
if (OB_ISNULL(rs_list)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("rs_list is null", K(ret));
|
|
} else if (json::JT_ARRAY != rs_list->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("rs list is not array", K(ret), "type", rs_list->get_type());
|
|
} else {
|
|
ObString addr_str;
|
|
ObString role_str;
|
|
// traverse rs_list array
|
|
DLIST_FOREACH(it, rs_list->get_array()) {
|
|
if (json::JT_OBJECT != it->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("not object in array", K(ret), "type", it->get_type());
|
|
break;
|
|
}
|
|
addr_str.reset();
|
|
role_str.reset();
|
|
int64_t sql_port = OB_INVALID_INDEX;
|
|
DLIST_FOREACH(p, it->get_object()) {
|
|
if (p->name_.case_compare(JSON_ADDRESS) == 0) {
|
|
if (NULL == p->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_STRING != p->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected address type", K(ret), "type", p->value_->get_type());
|
|
} else {
|
|
addr_str = p->value_->get_string();
|
|
}
|
|
} else if (p->name_.case_compare(JSON_ROLE) == 0) {
|
|
if (NULL == p->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_STRING != p->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected role type", K(ret), "type", p->value_->get_type());
|
|
} else {
|
|
role_str = p->value_->get_string();
|
|
}
|
|
} else if (p->name_.case_compare(JSON_SQL_PORT) == 0) {
|
|
if (NULL == p->value_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL value pointer", K(ret));
|
|
} else if (json::JT_NUMBER != p->value_->get_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected sql_port type", K(ret), "type", p->value_->get_type());
|
|
} else {
|
|
sql_port = p->value_->get_number();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (addr_str.empty()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("no address found in rs object", K(ret));
|
|
} else if (OB_FAIL(add_to_list(addr_str, sql_port, role_str, addr_list))) {
|
|
LOG_WARN("add address to list failed", K(ret),
|
|
K(addr_str), K(sql_port), K(role_str));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::add_to_list(common::ObString &addr_str, const int64_t sql_port,
|
|
common::ObString &role_str, ObIAddrList &addr_list)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (addr_str.empty() || sql_port <= 0 || role_str.empty()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(addr_str), K(sql_port), K(role_str));
|
|
} else {
|
|
ObRootAddr rs;
|
|
ObAddr addr;
|
|
ObRole role;
|
|
if (OB_FAIL(addr.parse_from_string(addr_str))) {
|
|
LOG_WARN("convert string to address failed", K(ret), K(addr_str));
|
|
} else {
|
|
if (role_str.case_compare("LEADER") == 0) {
|
|
role = LEADER;
|
|
} else if (role_str.case_compare("FOLLOWER") != 0) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid role string", K(ret), K(role));
|
|
} else {
|
|
role = FOLLOWER;
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(rs.init(addr, role, sql_port))) {
|
|
LOG_WARN("failed to simple init", KR(ret), K(addr), K(role), K(sql_port));
|
|
} else if (OB_FAIL(addr_list.push_back(rs))) {
|
|
LOG_WARN("add to array failed", K(ret), K(rs));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::to_json(
|
|
const ObIAddrList &addr_list,
|
|
const ObIAddrList &readonly_addr_list,
|
|
const char *appname,
|
|
const int64_t cluster_id,
|
|
const common::ObClusterRole cluster_role,
|
|
const int64_t timestamp,
|
|
common::ObSqlString &json)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const char* type_str = (PRIMARY_CLUSTER == cluster_role) ? JSON_PRIMARY : JSON_STANDBY;
|
|
// TODO support get RS list
|
|
if (OB_ISNULL(appname)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), "addr count", addr_list.count(), KP(appname));
|
|
} else if (OB_FAIL(json.append_fmt("{\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":%ld,\"%s\":%ld,\"%s\":\"%s\",\"%s\":%ld,\"%s\":[",
|
|
JSON_OB_REGION, appname,
|
|
JSON_OB_CLUSTER, appname,
|
|
JSON_OB_REGION_ID, cluster_id,
|
|
JSON_OB_CLUSTER_ID, cluster_id,
|
|
JSON_TYPE, type_str, JSON_TIMESTAMP, timestamp, JSON_RS_LIST))) {
|
|
LOG_WARN("assign string failed", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < addr_list.count(); ++i) {
|
|
if (i > 0) {
|
|
if (OB_FAIL(json.append(","))) {
|
|
LOG_WARN("append string failed", K(ret));
|
|
}
|
|
}
|
|
char ip_buf[OB_IP_STR_BUFF] = "";
|
|
ObRole role = addr_list.at(i).get_role();
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!addr_list.at(i).get_server().ip_to_string(ip_buf, sizeof(ip_buf))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("convert ip to string failed", K(ret), "server", addr_list.at(i).get_server());
|
|
} else if (!is_strong_leader(role) && !is_follower(role)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid role type", K(ret), K(role));
|
|
} else if (OB_FAIL(json.append_fmt("{\"%s\":\"%s:%d\",\"%s\":\"%s\",\"%s\":%ld}",
|
|
|
|
JSON_ADDRESS, ip_buf, addr_list.at(i).get_server().get_port(),
|
|
JSON_ROLE, is_strong_leader(role) ? "LEADER" : "FOLLOWER",
|
|
JSON_SQL_PORT, addr_list.at(i).get_sql_port()))) {
|
|
LOG_WARN("append string failed", K(ret));
|
|
}
|
|
}
|
|
|
|
// generate readonly_rs_list
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(json.append_fmt("],\"%s\":[", JSON_READONLY_RS_LIST))) {
|
|
LOG_WARN("append string failed", K(ret));
|
|
}
|
|
}
|
|
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < readonly_addr_list.count(); ++i) {
|
|
if (i > 0) {
|
|
if (OB_FAIL(json.append(","))) {
|
|
LOG_WARN("append string failed", K(ret));
|
|
}
|
|
}
|
|
char ip_buf[OB_IP_STR_BUFF] = "";
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!readonly_addr_list.at(i).get_server().ip_to_string(ip_buf, sizeof(ip_buf))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("convert ip to string failed", K(ret), "server", readonly_addr_list.at(i).get_server());
|
|
} else if (OB_FAIL(json.append_fmt("{\"%s\":\"%s:%d\",\"%s\":\"%s\",\"%s\":%ld}",
|
|
JSON_ADDRESS, ip_buf, readonly_addr_list.at(i).get_server().get_port(),
|
|
JSON_ROLE, "FOLLOWER",
|
|
JSON_SQL_PORT, readonly_addr_list.at(i).get_sql_port()))) {
|
|
LOG_WARN("append string failed", K(ret));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(json.append_fmt("]}"))) {
|
|
LOG_WARN("append string failed", K(ret));
|
|
} else {
|
|
LOG_INFO("to json success", K(json));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObWebServiceRootAddr::call_service(const char *post_data,
|
|
common::ObSqlString &content,
|
|
const char *config_url,
|
|
const int64_t timeout_ms,
|
|
const bool is_delete)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t begin = ObTimeUtility::current_time();
|
|
CURL *curl = curl_easy_init();
|
|
// post_data can be NULL for http get.
|
|
if (NULL == config_url || timeout_ms <= 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), KP(config_url), K(timeout_ms));
|
|
} else if (NULL == curl) {
|
|
ret = OB_CURL_ERROR;
|
|
LOG_WARN("init curl failed", K(ret));
|
|
} else {
|
|
// set options
|
|
CURLcode cc = CURLE_OK;
|
|
struct curl_slist *list = NULL;
|
|
if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_URL, config_url))) {
|
|
LOG_WARN("set url failed", K(cc), "url", config_url);
|
|
} else {
|
|
if (NULL != post_data) {
|
|
if (NULL == (list = curl_slist_append(list, "Content-Type: application/json"))) {
|
|
cc = CURLE_OUT_OF_MEMORY;
|
|
LOG_WARN("append list failed", K(cc));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list))) {
|
|
LOG_WARN("set http header failed", K(cc));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(
|
|
curl, CURLOPT_POSTFIELDSIZE, strlen(post_data)))) {
|
|
LOG_WARN("set post data size failed", K(cc), "size", strlen(post_data));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data))) {
|
|
LOG_WARN("set post data failed", K(cc), K(post_data));
|
|
} else if (is_delete
|
|
&& CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"))) {
|
|
LOG_WARN("fail to set option", KR(ret));
|
|
} else {
|
|
LOG_INFO("post data success", K(post_data));
|
|
}
|
|
}
|
|
}
|
|
|
|
const int64_t no_signal = 1;
|
|
const int64_t no_delay = 1;
|
|
const int64_t max_redirect = 3; // set max redirect
|
|
const int64_t follow_location = 1; // for http redirect 301 302
|
|
if (CURLE_OK != cc) {
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, no_signal))) {
|
|
LOG_WARN("set no signal failed", K(cc), K(no_signal));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_ms))) {
|
|
LOG_WARN("set timeout failed", K(cc), K(timeout_ms));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, timeout_ms))) {
|
|
LOG_WARN("set connect timeout failed", K(cc), K(timeout_ms));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, no_delay))) {
|
|
LOG_WARN("set no delay failed", K(cc), K(no_delay));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, max_redirect))) {
|
|
LOG_WARN("set max redirect failed", K(cc), K(max_redirect));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, follow_location))) {
|
|
LOG_WARN("set follow location failed", K(cc), K(follow_location));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(
|
|
curl, CURLOPT_WRITEFUNCTION, &curl_write_data))) {
|
|
LOG_WARN("set write function failed", K(cc));
|
|
} else if (CURLE_OK != (cc = curl_easy_setopt(
|
|
curl, CURLOPT_WRITEDATA, &content))) {
|
|
LOG_WARN("set write data failed", K(cc));
|
|
}
|
|
|
|
// send && recv
|
|
int64_t http_code = 0;
|
|
if (CURLE_OK != cc) {
|
|
} else if (CURLE_OK != (cc = curl_easy_perform(curl))) {
|
|
LOG_WARN("curl easy perform failed", K(cc));
|
|
} else if (CURLE_OK != (cc = curl_easy_getinfo(
|
|
curl, CURLINFO_RESPONSE_CODE, &http_code))) {
|
|
LOG_WARN("curl getinfo failed", K(cc));
|
|
} else {
|
|
// http status code 2xx means success
|
|
if (http_code / 100 != 2) {
|
|
ret = OB_CURL_ERROR;
|
|
LOG_WARN("unexpected http status code", K(ret), K(http_code), K(content));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (CURLE_OK != cc) {
|
|
ret = OB_CURL_ERROR;
|
|
LOG_WARN("curl error", K(ret), "curl_error_code", cc,
|
|
"curl_error_message", curl_easy_strerror(cc));
|
|
}
|
|
}
|
|
if (NULL != list) {
|
|
curl_slist_free_all(list);
|
|
list = NULL;
|
|
}
|
|
}
|
|
if (NULL != curl) {
|
|
curl_easy_cleanup(curl);
|
|
curl = NULL;
|
|
}
|
|
const int64_t consume_time = ObTimeUtility::current_time() - begin;
|
|
LOG_TRACE("call service", K(ret), K(consume_time),
|
|
"method", NULL == post_data ? "GET" : "POST");
|
|
return ret;
|
|
}
|
|
|
|
int64_t ObWebServiceRootAddr::curl_write_data(
|
|
void *ptr, int64_t size, int64_t nmemb, void *stream)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
// This function may be called with zero bytes data if the transferred file is empty.
|
|
if (NULL == stream || size < 0 || nmemb < 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(ret), K(stream), K(size), K(nmemb));
|
|
} else {
|
|
ObSqlString *content = static_cast<ObSqlString *>(stream);
|
|
if (size * nmemb > 0) {
|
|
if (NULL == ptr) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("receive data but pointer is NULL", K(ret), KP(ptr), K(size), K(nmemb));
|
|
} else if (size * nmemb + content->length() > MAX_RECV_CONTENT_LEN) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("unexpected long content", K(ret),
|
|
"new_byte", size * nmemb,
|
|
"received_byte", content->length(),
|
|
LITERAL_K(MAX_RECV_CONTENT_LEN));
|
|
} else if (OB_FAIL(content->append(static_cast<const char *>(ptr), size * nmemb))) {
|
|
LOG_WARN("append data failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
return OB_SUCCESS == ret ? size * nmemb : 0;
|
|
}
|
|
|
|
|
|
//{
|
|
// "Message": "successful",
|
|
// "Success": true,
|
|
// "Code": 200,
|
|
// "Data": [{
|
|
// "ObRegion": "ob2.rongxuan.lc",
|
|
// "ObRegionId": 2,
|
|
// "RsList": [{
|
|
// "address": "10.101.67.165:16825",
|
|
// "role": "LEADER",
|
|
// "sql_port": 16860
|
|
// }, {
|
|
// "address": "10.218.78.76:16827",
|
|
// "role": "FOLLOWER",
|
|
// "sql_port": 16862
|
|
// }],
|
|
// "ReadonlyRsList": []
|
|
// }]
|
|
//}
|
|
|
|
int ObWebServiceRootAddr::get_all_cluster_info(common::ObServerConfig *config,
|
|
ObClusterIAddrList &cluster_list)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(config);
|
|
cluster_list.reset();
|
|
//if (OB_ISNULL(config)) {
|
|
// ret = OB_INVALID_ARGUMENT;
|
|
// LOG_WARN("invalid argument", K(ret), K(config));
|
|
//} else {
|
|
// const char *url = config->obconfig_url.str();
|
|
// const char *appname = config->cluster.str();
|
|
// int64_t timeout_ms = config->rpc_timeout / 1000;
|
|
// const int64_t buf_len = OB_MAX_CONFIG_URL_LENGTH;
|
|
// char buf[buf_len] = {'\0'};
|
|
// if (NULL == url || NULL == appname || timeout_ms <= 0) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_ERROR("NULL url or NULL appname or invalid timeout",
|
|
// K(ret), KP(url), KP(appname), K(timeout_ms));
|
|
// } else {
|
|
// int64_t pos = 0;
|
|
// ObString tmp_url(strlen(url), url);
|
|
// if (OB_ISNULL(tmp_url.find('?'))) {
|
|
// BUF_PRINTF("%s?%s=2", url, JSON_VERSION);
|
|
// } else {
|
|
// BUF_PRINTF("%s&%s=2", url, JSON_VERSION);
|
|
// }
|
|
// }
|
|
// ObSqlString json;
|
|
// if (OB_FAIL(ret)) {
|
|
// } else if (OB_FAIL(call_service(NULL, json, buf, timeout_ms))) {
|
|
// LOG_WARN("fail to call service", K(ret), K(buf));
|
|
// } else if (json.empty()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("web service returned empty result", K(ret));
|
|
// } else if (OB_FAIL(get_all_cluster_info(json.ptr(), cluster_list))) {
|
|
// LOG_WARN("fail to get all cluster addr", K(ret), K(json), K(buf));
|
|
// } else {
|
|
// LOG_INFO("get all cluster addr success", K(cluster_list));
|
|
// }
|
|
//}
|
|
return ret;
|
|
}
|
|
|
|
//int ObWebServiceRootAddr::get_all_cluster_info(const char *json_str,
|
|
// ObClusterIAddrList &cluster_list)
|
|
//{
|
|
// int ret = OB_SUCCESS;
|
|
// ObArenaAllocator allocator(ObModIds::OB_JSON_PARSER);
|
|
// json::Parser parser;
|
|
// json::Value *root = NULL;
|
|
// if (NULL == json_str) {
|
|
// ret = OB_INVALID_ARGUMENT;
|
|
// LOG_WARN("invalid argument", K(ret), KP(json_str));
|
|
// } else if (OB_FAIL(parser.init(&allocator))) {
|
|
// LOG_WARN("json parser init failed", K(ret));
|
|
// } else if (OB_FAIL(parser.parse(json_str, strlen(json_str), root))) {
|
|
// LOG_WARN("parse json failed", K(ret), K(json_str));
|
|
// } else if (NULL == root) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("no root value", K(ret));
|
|
// } else {
|
|
// cluster_list.reuse();
|
|
// json::Value *data = NULL;
|
|
// // check return code and get data filed
|
|
// if (json::JT_OBJECT != root->get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("error json format", K(ret), K(json_str), "root", *root);
|
|
// } else {
|
|
// DLIST_FOREACH(it, root->get_object()) {
|
|
// if (it->name_.case_compare(JSON_RES_DATA) == 0) {
|
|
// data = it->value_;
|
|
// }
|
|
// if (it->name_.case_compare(JSON_RES_CODE) == 0) {
|
|
// if (NULL == it->value_) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("NULL value pointer", K(ret));
|
|
// } else if (json::JT_NUMBER != it->value_->get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("unexpected code type", K(ret), "type", it->value_->get_type());
|
|
// } else {
|
|
// const int64_t code = it->value_->get_number();
|
|
// if (200 != code) {
|
|
// ret = OB_OBCONFIG_RETURN_ERROR;
|
|
// LOG_WARN("return code not success", K(ret), K(code));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// // check appname and get data
|
|
// if (OB_SUCC(ret)) {
|
|
// if (OB_ISNULL(data)) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("no data filed found", K(ret));
|
|
// } else if (json::JT_ARRAY != data->get_type()) {
|
|
// ret = OB_INVALD_WEB_SERVICE_CONTENT;
|
|
// LOG_WARN("data filed not array", K(ret), "data", *data);
|
|
// } else {
|
|
// ObClusterAddr cluster_addr;
|
|
// DLIST_FOREACH(it, data->get_array()) {
|
|
// if (json::JT_OBJECT != it->get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("not object in array", K(ret), "type", it->get_type());
|
|
// break;
|
|
// }
|
|
// cluster_addr.reset();
|
|
// DLIST_FOREACH(p, it->get_object()) {
|
|
// if (p->name_.case_compare(JSON_OB_CLUSTER) == 0) {
|
|
// if (OB_ISNULL(p->value_)) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("NULL value pointer", K(ret));
|
|
// } else if (json::JT_STRING != p->value_->get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("unexpected address type", K(ret), "type", p->value_->get_type());
|
|
// } else {
|
|
// cluster_addr.cluster_name_ = p->value_->get_string();
|
|
// }
|
|
// } else if (p->name_.case_compare(JSON_TIMESTAMP) == 0) {
|
|
// if (NULL == p->value_) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("NULL value pointer", K(ret));
|
|
// } else if (json::JT_NUMBER != p->value_->get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("unexpected cluster_id type", K(ret), "type", p->value_->get_type());
|
|
// } else {
|
|
// cluster_addr.timestamp_ = p->value_->get_number();
|
|
// }
|
|
// } else if (p->name_.case_compare(JSON_OB_CLUSTER_ID) == 0) {
|
|
// if (NULL == p->value_) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("NULL value pointer", K(ret));
|
|
// } else if (json::JT_NUMBER != p->value_->get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("unexpected cluster_id type", K(ret), "type", p->value_->get_type());
|
|
// } else {
|
|
// cluster_addr.cluster_id_ = p->value_->get_number();
|
|
// }
|
|
// } else if (p->name_.case_compare(JSON_TYPE) == 0) {
|
|
// if (OB_ISNULL(p->value_)) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("NULL value pointer", K(ret));
|
|
// } else if (json::JT_STRING != p->value_->get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("unexpected cluster type", K(ret), "type", p->value_->get_type());
|
|
// } else if (p->value_->get_string().case_compare(JSON_PRIMARY) == 0) {
|
|
// cluster_addr.cluster_role_ = PRIMARY_CLUSTER;
|
|
// } else if (p->value_->get_string().case_compare(JSON_STANDBY) == 0) {
|
|
// cluster_addr.cluster_role_ = STANDBY_CLUSTER;
|
|
// } else {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("invalid cluster type", K(ret), "type", p->value_->get_string());
|
|
// }
|
|
// } else if (p->name_.case_compare(JSON_RS_LIST) == 0) {
|
|
// if (OB_FAIL(get_addr_list(p->value_, cluster_addr.addr_list_))) {
|
|
// LOG_WARN("fail to get addr list", K(ret), K(p));
|
|
// }
|
|
// } else if (p->name_.case_compare(JSON_READONLY_RS_LIST) == 0) {
|
|
// if (OB_FAIL(get_addr_list(p->value_, cluster_addr.readonly_addr_list_))) {
|
|
// LOG_WARN("fail to get addr list", K(ret), K(p));
|
|
// }
|
|
// }
|
|
// }
|
|
// if (OB_FAIL(ret)) {
|
|
// //nothing todo
|
|
// } else if (OB_FAIL(cluster_list.push_back(cluster_addr))) {
|
|
// LOG_WARN("fail to push back cluster addr", K(ret), K(cluster_addr));
|
|
// } else {
|
|
// LOG_INFO("push back cluster addr success", K(cluster_addr));
|
|
// }
|
|
// } //end DLIST_FOREACH(it, data->get_array(
|
|
// }
|
|
// }
|
|
// }
|
|
// return ret;
|
|
//}
|
|
|
|
|
|
static const char *redo_transport_options_strs[] = {"SYNC", "ASYNC", "NET_TIMEOUT", "REOPEN", "MAX_FAILURE"};
|
|
|
|
|
|
ObRedoTransportOption::RedoOptionProfile ObRedoTransportOption::str_to_redo_transport_options(const char *str)
|
|
{
|
|
RedoOptionProfile redo_transport_options = RedoOptionProfile::INVALID_TYPE;
|
|
if (OB_ISNULL(str)) {
|
|
//nothing
|
|
} else {
|
|
ObString option(str);
|
|
for (int64_t i = 0; i < ARRAYSIZEOF(redo_transport_options_strs); i++) {
|
|
if (0 == option.case_compare(redo_transport_options_strs[i])) {
|
|
redo_transport_options = static_cast<RedoOptionProfile>(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return redo_transport_options;
|
|
}
|
|
OB_SERIALIZE_MEMBER(ObRedoTransportOption, net_timeout_, reopen_, max_failure_, is_sync_);
|
|
|
|
int ObRedoTransportOption::append_redo_transport_options_change(
|
|
const ObString &redo_transport_options_str) {
|
|
int ret = OB_SUCCESS;
|
|
//incremental update
|
|
if (redo_transport_options_str.empty()) {
|
|
} else {
|
|
SMART_VAR(char[OB_MAX_CONFIG_VALUE_LEN], format_str) {
|
|
if (OB_FAIL(ObConfigLogArchiveOptionsItem::format_option_str(
|
|
to_cstring(redo_transport_options_str),
|
|
redo_transport_options_str.length(),
|
|
format_str,
|
|
OB_MAX_CONFIG_VALUE_LEN))) {
|
|
LOG_WARN("failed to format option str", KR(ret));
|
|
} else {
|
|
char *saveptr = NULL;
|
|
char *key_name = STRTOK_R(format_str, " ", &saveptr);
|
|
while(OB_NOT_NULL(key_name) && OB_SUCC(ret)) {
|
|
char *s = NULL;
|
|
char *value_str = NULL;
|
|
RedoOptionProfile redo_transport_options = str_to_redo_transport_options(key_name);
|
|
if (RedoOptionProfile::INVALID_TYPE == redo_transport_options) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("failed to construct redo option", KR(ret),
|
|
K(redo_transport_options_str), K(redo_transport_options));
|
|
} else if (RedoOptionProfile::SYNC == redo_transport_options) {
|
|
is_sync_ = true;
|
|
} else if (RedoOptionProfile::ASYNC == redo_transport_options) {
|
|
is_sync_ = false;
|
|
} else if (OB_ISNULL(s = STRTOK_R(NULL, " ", &saveptr))) {
|
|
ret = OB_ERR_PARAM_INVALID;
|
|
LOG_WARN("failed to get value", KR(ret), K(saveptr));
|
|
} else if (0 != ObString::make_string("=").case_compare(s)) {
|
|
ret = OB_ERR_PARAM_INVALID;
|
|
LOG_WARN("expect \"=\"", KR(ret), K(s), K(saveptr));
|
|
} else if (OB_ISNULL(value_str = STRTOK_R(NULL, " ", &saveptr))) {
|
|
ret = OB_ERR_PARAM_INVALID;
|
|
LOG_WARN("failed to get value", KR(ret), K(saveptr));
|
|
} else {
|
|
int64_t value = 0;
|
|
if (OB_FAIL(ob_atoll(value_str, value))) {
|
|
LOG_WARN("failed to get number", KR(ret), K(value_str));
|
|
} else if (OB_UNLIKELY(value < 0)) {
|
|
ret = OB_ERR_PARAM_INVALID;
|
|
LOG_WARN("value should not be negative number", KR(ret), K(value_str));
|
|
} else if (RedoOptionProfile::NET_TIMEOUT == redo_transport_options) {
|
|
net_timeout_ = value;
|
|
} else if (RedoOptionProfile::REOPEN == redo_transport_options) {
|
|
reopen_ = value;
|
|
} else if (RedoOptionProfile::MAX_FAILURE == redo_transport_options) {
|
|
max_failure_ = value;
|
|
} else {
|
|
ret = OB_ERR_PARAM_INVALID;
|
|
LOG_WARN("unknown redo option", KR(ret), K(redo_transport_options));
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else {
|
|
key_name = STRTOK_R(NULL, " ", &saveptr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObRedoTransportOption::assign(const ObRedoTransportOption &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (this != &other) {
|
|
net_timeout_ = other.net_timeout_;
|
|
reopen_ = other.reopen_;
|
|
max_failure_ = other.max_failure_;
|
|
is_sync_ = other.is_sync_;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ObRedoTransportOption& ObRedoTransportOption::operator=(const ObRedoTransportOption &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (this != &other) {
|
|
if (OB_FAIL(assign(other))) {
|
|
LOG_WARN("fail to assign", KR(ret), K(other));
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool ObRedoTransportOption::operator!=(const ObRedoTransportOption &other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
bool ObRedoTransportOption::operator==(const ObRedoTransportOption &other) const
|
|
{
|
|
return net_timeout_ == other.net_timeout_
|
|
&& reopen_ == other.reopen_
|
|
&& max_failure_ == other.max_failure_
|
|
&& is_sync_ == other.is_sync_;
|
|
}
|
|
|
|
int ObRedoTransportOption::get_redo_transport_options_str(ObSqlString &str) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_sync_) {
|
|
if (OB_FAIL(str.assign("SYNC "))) {
|
|
LOG_WARN("failed to assign str", KR(ret));
|
|
}
|
|
} else if (OB_FAIL(str.assign("ASYNC "))) {
|
|
LOG_WARN("failed to assign str", KR(ret));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(str.append_fmt("NET_TIMEOUT = %ld",
|
|
net_timeout_))) {
|
|
LOG_WARN("failed to assign str", KR(ret), "this", *this);
|
|
}
|
|
return ret;
|
|
}
|
|
} // end namespace share
|
|
} // end oceanbase
|