Files
doris/be/src/util/mysql_load_error_hub.cpp
2022-02-19 11:29:02 +08:00

142 lines
4.3 KiB
C++

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <mysql/mysql.h>
#define __DorisMysql MYSQL
#include "mysql_load_error_hub.h"
#include "util/defer_op.h"
namespace doris {
MysqlLoadErrorHub::MysqlLoadErrorHub(const TMysqlErrorHubInfo& info) : _info(info) {}
MysqlLoadErrorHub::~MysqlLoadErrorHub() {}
Status MysqlLoadErrorHub::prepare() {
_is_valid = true;
return Status::OK();
}
Status MysqlLoadErrorHub::export_error(const ErrorMsg& error_msg) {
std::lock_guard<std::mutex> lock(_mtx);
++_total_error_num;
if (!_is_valid) {
return Status::OK();
}
_error_msgs.push(error_msg);
if (_error_msgs.size() >= EXPORTER_THRESHOLD) {
RETURN_IF_ERROR(write_mysql());
}
return Status::OK();
}
Status MysqlLoadErrorHub::close() {
std::lock_guard<std::mutex> lock(_mtx);
if (!_is_valid) {
return Status::OK();
}
if (!_error_msgs.empty()) {
RETURN_IF_ERROR(write_mysql());
}
return Status::OK();
}
Status MysqlLoadErrorHub::write_mysql() {
MYSQL* my_conn = nullptr;
Status st = open_mysql_conn(&my_conn);
if (!st.ok()) {
_is_valid = false;
return st;
}
Defer close_mysql_conn {[=]() { mysql_close(my_conn); }};
Status status;
std::stringstream sql_stream;
while (!_error_msgs.empty()) {
status = gen_sql(my_conn, _error_msgs.front(), &sql_stream);
if (!status.ok()) {
return error_status("fail to gen sql", my_conn);
}
_error_msgs.pop();
}
int sql_result = mysql_query(my_conn, sql_stream.str().c_str());
if (sql_result != 0) {
LOG(WARNING) << "mysql insert failed. query=[" << sql_stream.str() << "]";
return error_status("mysql query failed.", my_conn);
}
VLOG_PROGRESS << "mysql query success. query =" << sql_stream.str();
return Status::OK();
}
Status MysqlLoadErrorHub::gen_sql(MYSQL* my_conn, const LoadErrorHub::ErrorMsg& error_msg,
std::stringstream* sql_stream) {
char* sql_start = &_escape_buff[0];
size_t msg_size = error_msg.msg.size();
if (msg_size > EXPORTER_MAX_LINE_SIZE) {
msg_size = EXPORTER_MAX_LINE_SIZE;
}
(*sql_stream) << "insert into " << _info.table << " (job_id, error_msg) values("
<< error_msg.job_id << ", '" << sql_start << "'); ";
return Status::OK();
}
Status MysqlLoadErrorHub::open_mysql_conn(MYSQL** my_conn) {
*my_conn = mysql_init(nullptr);
if (nullptr == *my_conn) {
LOG(WARNING) << "load error export's mysql init failed.";
return Status::InternalError("mysql init failed.");
}
VLOG_ROW << "MysqlLoadErrorHub::init";
if (!mysql_real_connect(*my_conn, _info.host.c_str(), _info.user.c_str(), _info.passwd.c_str(),
_info.db.c_str(), _info.port, nullptr, CLIENT_MULTI_STATEMENTS)) {
LOG(WARNING) << "fail to connect Mysql: "
<< "Host: " << _info.host << " port: " << _info.port << " user: " << _info.user
<< " passwd: " << _info.passwd << " db: " << _info.db;
return error_status("load error mysql real connect failed.", *my_conn);
}
return Status::OK();
}
Status MysqlLoadErrorHub::error_status(const std::string& prefix, MYSQL* my_conn) {
std::stringstream msg;
msg << prefix << " Err: " << mysql_error(my_conn);
LOG(WARNING) << msg.str();
return Status::InternalError(msg.str());
}
std::string MysqlLoadErrorHub::debug_string() const {
std::stringstream out;
out << "(total_error_num=" << _total_error_num << ")";
return out.str();
}
} // end namespace doris