/* * 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. */ // A brpc based command-line interface to talk with mysql-server #include #include #include extern "C" { #include } #include #include #include #include DEFINE_string(server, "127.0.0.1", "IP Address of server"); DEFINE_int32(port, 3306, "Port of server"); DEFINE_string(user, "brpcuser", "user name"); DEFINE_string(password, "12345678", "password"); DEFINE_string(schema, "brpc_test", "schema"); DEFINE_string(params, "", "params"); DEFINE_string(data, "ABCDEF", "data"); DEFINE_int32(thread_num, 50, "Number of threads to send requests"); DEFINE_bool(use_bthread, false, "Use bthread to send requests"); DEFINE_int32(dummy_port, -1, "port of dummy server(for monitoring)"); DEFINE_int32(op_type, 0, "CRUD operation, 0:INSERT, 1:SELECT, 3:UPDATE"); DEFINE_bool(dont_fail, false, "Print fatal when some call failed"); bvar::LatencyRecorder g_latency_recorder("client"); bvar::Adder g_error_count("client_error_count"); struct SenderArgs { int base_index; MYSQL* mysql_conn; }; const std::string insert = "insert into mysqlclient_press(col1,col2,col3,col4) values " "('" "ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCA" "BCABCABCABCABCABCABCA', '" + FLAGS_data + "' ,1.5, " "now())"; // Send `command' to mysql-server via `channel' static void* sender(void* void_args) { SenderArgs* args = (SenderArgs*)void_args; std::stringstream command; if (FLAGS_op_type == 0) { command << insert; } else if (FLAGS_op_type == 1) { command << "select * from mysqlclient_press where id = " << args->base_index + 1; } else if (FLAGS_op_type == 2) { command << "update brpc_press set col2 = '" + FLAGS_data + "' where id = " << args->base_index + 1; } else { LOG(ERROR) << "wrong op type " << FLAGS_op_type; } std::string command_str = command.str(); while (!brpc::IsAskedToQuit()) { const int64_t begin_time_us = butil::cpuwide_time_us(); const int rc = mysql_real_query(args->mysql_conn, command_str.c_str(), command_str.size()); if (rc != 0) { goto ERROR; } if (mysql_errno(args->mysql_conn) == 0) { if (FLAGS_op_type == 0) { CHECK_EQ(mysql_affected_rows(args->mysql_conn), 1); } else if (FLAGS_op_type == 1) { MYSQL_RES* res = mysql_store_result(args->mysql_conn); if (res == NULL) { LOG(INFO) << "not found"; } else { CHECK_EQ(mysql_num_rows(res), 1); mysql_free_result(res); } } else if (FLAGS_op_type == 2) { } const int64_t elp = butil::cpuwide_time_us() - begin_time_us; g_latency_recorder << elp; } else { goto ERROR; } if (false) { ERROR: const int64_t elp = butil::cpuwide_time_us() - begin_time_us; g_error_count << 1; CHECK(brpc::IsAskedToQuit() || !FLAGS_dont_fail) << "error=" << mysql_error(args->mysql_conn) << " latency=" << elp; // We can't connect to the server, sleep a while. Notice that this // is a specific sleeping to prevent this thread from spinning too // fast. You should continue the business logic in a production // server rather than sleeping. bthread_usleep(50000); } } return NULL; } int main(int argc, char* argv[]) { // Parse gflags. We recommend you to use gflags as well. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); if (FLAGS_dummy_port >= 0) { brpc::StartDummyServerAt(FLAGS_dummy_port); } MYSQL* conn = mysql_init(NULL); if (!mysql_real_connect(conn, FLAGS_server.c_str(), FLAGS_user.c_str(), FLAGS_password.c_str(), FLAGS_schema.c_str(), FLAGS_port, NULL, 0)) { LOG(ERROR) << mysql_error(conn); return -1; } // create table mysqlclient_press { const char* sql = "CREATE TABLE IF NOT EXISTS `mysqlclient_press`(`id` INT UNSIGNED AUTO_INCREMENT, " "`col1` " "VARCHAR(100) NOT NULL, `col2` VARCHAR(1024) NOT NULL, `col3` decimal(10,0) NOT " "NULL, `col4` DATE, PRIMARY KEY ( `id` )) ENGINE=InnoDB DEFAULT CHARSET=utf8;"; const int rc = mysql_real_query(conn, sql, strlen(sql)); if (rc != 0) { LOG(ERROR) << "Fail to execute sql, " << mysql_error(conn); return -1; } if (mysql_errno(conn) != 0) { LOG(ERROR) << "Fail to store result, " << mysql_error(conn); return -1; } } // truncate table { const char* sql = "truncate table mysqlclient_press"; const int rc = mysql_real_query(conn, sql, strlen(sql)); if (rc != 0) { LOG(ERROR) << "Fail to execute sql, " << mysql_error(conn); return -1; } if (mysql_errno(conn) != 0) { LOG(ERROR) << "Fail to store result, " << mysql_error(conn); return -1; } } // prepare data for select, update if (FLAGS_op_type != 0) { for (int i = 0; i < FLAGS_thread_num; ++i) { const int rc = mysql_real_query(conn, insert.c_str(), insert.size()); if (rc != 0) { LOG(ERROR) << "Fail to execute sql, " << mysql_error(conn); return -1; } if (mysql_errno(conn) != 0) { LOG(ERROR) << "Fail to store result, " << mysql_error(conn); return -1; } } } // test CRUD operations std::vector bids; std::vector pids; bids.resize(FLAGS_thread_num); pids.resize(FLAGS_thread_num); std::vector args; args.resize(FLAGS_thread_num); for (int i = 0; i < FLAGS_thread_num; ++i) { MYSQL* conn = mysql_init(NULL); if (!mysql_real_connect(conn, FLAGS_server.c_str(), FLAGS_user.c_str(), FLAGS_password.c_str(), FLAGS_schema.c_str(), FLAGS_port, NULL, 0)) { LOG(ERROR) << mysql_error(conn); return -1; } args[i].base_index = i; args[i].mysql_conn = conn; if (!FLAGS_use_bthread) { if (pthread_create(&pids[i], NULL, sender, &args[i]) != 0) { LOG(ERROR) << "Fail to create pthread"; return -1; } } else { if (bthread_start_background(&bids[i], NULL, sender, &args[i]) != 0) { LOG(ERROR) << "Fail to create bthread"; return -1; } } } while (!brpc::IsAskedToQuit()) { sleep(1); LOG(INFO) << "Accessing mysql-server at qps=" << g_latency_recorder.qps(1) << " latency=" << g_latency_recorder.latency(1); } LOG(INFO) << "mysql_client is going to quit"; for (int i = 0; i < FLAGS_thread_num; ++i) { if (!FLAGS_use_bthread) { pthread_join(pids[i], NULL); } else { bthread_join(bids[i], NULL); } } return 0; }