292 lines
8.2 KiB
C++
292 lines
8.2 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 <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
#define private public
|
|
#include "lib/io/ob_io_manager.h"
|
|
#undef private
|
|
#include "lib/io/ob_io_benchmark.h"
|
|
#include "lib/file/file_directory_utils.h"
|
|
#include "ob_io_stress.h"
|
|
|
|
using namespace oceanbase::obsys;
|
|
using namespace oceanbase::lib;
|
|
using namespace ::testing;
|
|
|
|
namespace oceanbase {
|
|
namespace common {
|
|
class TestDiskError : public ::testing::Test {
|
|
public:
|
|
TestDiskError()
|
|
{}
|
|
virtual ~TestDiskError()
|
|
{}
|
|
virtual void SetUp();
|
|
virtual void TearDown();
|
|
virtual void prepare_conf(const int trigger_fd, int submit_fail, int io_hang, int io_timeout);
|
|
virtual void preapre_stress(const int64_t submit_thread_cnt = 1);
|
|
virtual void start_stress();
|
|
virtual void stop_stress();
|
|
virtual void destroy_stress();
|
|
virtual void set_no_wait();
|
|
virtual void set_io_size(const int64_t disk_index, const int64_t io_size);
|
|
|
|
protected:
|
|
static const int64_t DISK_CNT = 2;
|
|
int64_t file_size_;
|
|
char file_names_[DISK_CNT][128];
|
|
int fds_[DISK_CNT];
|
|
TestIOStress stress_[DISK_CNT];
|
|
};
|
|
|
|
void TestDiskError::SetUp()
|
|
{
|
|
file_size_ = 1024L * 1024L * 1024L;
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().init());
|
|
prepare_conf(-1, 0, 0, 0);
|
|
sleep(10);
|
|
}
|
|
|
|
void TestDiskError::TearDown()
|
|
{
|
|
ObIOManager::get_instance().destroy();
|
|
}
|
|
|
|
void TestDiskError::prepare_conf(const int trigger_fd, int submit_fail, int io_hang, int io_timeout)
|
|
{
|
|
int fd = ::open("aio_conf", O_CREAT | O_TRUNC | O_RDWR);
|
|
ASSERT_TRUE(fd > 0);
|
|
char buf[64];
|
|
memset(buf, 0, sizeof(buf));
|
|
snprintf(buf, sizeof(buf), "%d,%d,%d,%d", trigger_fd, submit_fail, io_hang, io_timeout);
|
|
::write(fd, buf, strlen(buf));
|
|
::close(fd);
|
|
}
|
|
|
|
void TestDiskError::preapre_stress(const int64_t submit_thread_cnt)
|
|
{
|
|
UNUSED(submit_thread_cnt);
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
snprintf(file_names_[i], 128, "./test_io_manager%ld", (i + 1));
|
|
}
|
|
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
fds_[i] = ::open(file_names_[i], O_CREAT | O_TRUNC | O_RDWR | O_DIRECT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
|
ASSERT_TRUE(fds_[i] > 0);
|
|
ftruncate(fds_[i], file_size_);
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().add_disk(fds_[i], ObDisk::DEFAULT_SYS_IO_PERCENT));
|
|
}
|
|
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
stress_[i].init(fds_[i], file_size_, 3, 1, 0);
|
|
}
|
|
}
|
|
|
|
void TestDiskError::start_stress()
|
|
{
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
stress_[i].start();
|
|
}
|
|
}
|
|
|
|
void TestDiskError::stop_stress()
|
|
{
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
stress_[i].stop();
|
|
stress_[i].wait();
|
|
}
|
|
}
|
|
|
|
void TestDiskError::destroy_stress()
|
|
{
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().delete_disk(fds_[i]));
|
|
::close(fds_[i]);
|
|
FileDirectoryUtils::delete_file(file_names_[i]);
|
|
}
|
|
}
|
|
|
|
void TestDiskError::set_no_wait()
|
|
{
|
|
stress_[0].set_no_wait();
|
|
}
|
|
|
|
void TestDiskError::set_io_size(const int64_t disk_index, const int64_t io_size)
|
|
{
|
|
stress_[disk_index].set_user_io_size((int32_t)io_size);
|
|
}
|
|
|
|
TEST_F(TestDiskError, io_submit_failed)
|
|
{
|
|
preapre_stress();
|
|
prepare_conf(fds_[0], 1, 0, 0);
|
|
sleep(10);
|
|
start_stress();
|
|
sleep(15);
|
|
stop_stress();
|
|
|
|
// check result
|
|
ASSERT_TRUE(stress_[0].get_fail_count() > 0);
|
|
// ASSERT_TRUE(stress_[0].get_succeed_count() == 0);
|
|
ASSERT_TRUE(stress_[1].get_fail_count() == 0);
|
|
ASSERT_TRUE(stress_[0].get_succeed_count() > 0);
|
|
|
|
destroy_stress();
|
|
}
|
|
|
|
TEST_F(TestDiskError, io_hang_not_mark_error)
|
|
{
|
|
ObIOConfig config = ObIOManager::get_instance().get_io_config();
|
|
config.retry_warn_limit_ = 9;
|
|
config.retry_error_limit_ = 18;
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().set_io_config(config));
|
|
|
|
preapre_stress();
|
|
prepare_conf(fds_[0], 0, 1, 0);
|
|
sleep(10);
|
|
start_stress();
|
|
sleep(30);
|
|
stop_stress();
|
|
|
|
// check result
|
|
ASSERT_TRUE(stress_[0].get_fail_count() > 0);
|
|
// ASSERT_TRUE(stress_[0].get_succeed_count() == 0);
|
|
ASSERT_TRUE(stress_[1].get_fail_count() == 0);
|
|
ASSERT_TRUE(stress_[0].get_succeed_count() > 0);
|
|
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
// not mark error disk delete disk will timeout if io hang
|
|
ASSERT_EQ(0 == i ? OB_TIMEOUT : OB_SUCCESS, ObIOManager::get_instance().delete_disk(fds_[i]));
|
|
::close(fds_[i]);
|
|
FileDirectoryUtils::delete_file(file_names_[i]);
|
|
}
|
|
}
|
|
|
|
TEST_F(TestDiskError, io_hang_mark_error)
|
|
{
|
|
ObIOConfig config = ObIOManager::get_instance().get_io_config();
|
|
config.retry_warn_limit_ = 1;
|
|
config.retry_error_limit_ = 2;
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().set_io_config(config));
|
|
|
|
preapre_stress();
|
|
prepare_conf(fds_[0], 0, 1, 0);
|
|
sleep(10);
|
|
start_stress();
|
|
sleep(30);
|
|
stop_stress();
|
|
|
|
// check result
|
|
ASSERT_TRUE(stress_[0].get_fail_count() > 0);
|
|
// ASSERT_TRUE(stress_[0].get_succeed_count() == 0);
|
|
ASSERT_TRUE(stress_[1].get_fail_count() == 0);
|
|
ASSERT_TRUE(stress_[0].get_succeed_count() > 0);
|
|
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
// mark error disk delete disk will clean onging io request
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().delete_disk(fds_[i]));
|
|
::close(fds_[i]);
|
|
FileDirectoryUtils::delete_file(file_names_[i]);
|
|
}
|
|
}
|
|
|
|
TEST_F(TestDiskError, io_timeout)
|
|
{
|
|
ObIOConfig config = ObIOManager::get_instance().get_io_config();
|
|
config.retry_warn_limit_ = 1;
|
|
config.retry_error_limit_ = 2;
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().set_io_config(config));
|
|
|
|
preapre_stress();
|
|
prepare_conf(fds_[0], 0, 0, 1);
|
|
sleep(10);
|
|
start_stress();
|
|
sleep(30);
|
|
stop_stress();
|
|
|
|
// check result
|
|
ASSERT_TRUE(stress_[0].get_fail_count() > 0);
|
|
// ASSERT_TRUE(stress_[0].get_succeed_count() == 0);
|
|
ASSERT_TRUE(stress_[1].get_fail_count() == 0);
|
|
ASSERT_TRUE(stress_[0].get_succeed_count() > 0);
|
|
|
|
bool disk_error = false;
|
|
ASSERT_EQ(OB_SUCCESS, OB_IO_MANAGER.get_disk_manager().is_disk_error(fds_[0], disk_error));
|
|
ASSERT_TRUE(disk_error);
|
|
ASSERT_EQ(OB_SUCCESS, OB_IO_MANAGER.is_disk_error(disk_error));
|
|
ASSERT_TRUE(disk_error);
|
|
ObArray<ObDiskFd> error_disks;
|
|
ASSERT_EQ(OB_SUCCESS, OB_IO_MANAGER.get_disk_manager().get_error_disks(error_disks));
|
|
ASSERT_EQ(1, error_disks.count());
|
|
ASSERT_EQ(fds_[0], error_disks.at(0));
|
|
|
|
ASSERT_EQ(OB_SUCCESS, OB_IO_MANAGER.reset_disk_error());
|
|
ASSERT_EQ(OB_SUCCESS, OB_IO_MANAGER.is_disk_error(disk_error));
|
|
ASSERT_FALSE(disk_error);
|
|
|
|
COMMON_LOG(INFO, "start sleep");
|
|
sleep(30); // wait io finish
|
|
COMMON_LOG(INFO, "end sleep");
|
|
destroy_stress();
|
|
}
|
|
|
|
TEST_F(TestDiskError, io_hang2)
|
|
{
|
|
ObIOConfig config = ObIOManager::get_instance().get_io_config();
|
|
config.retry_warn_limit_ = 1;
|
|
config.retry_error_limit_ = 2;
|
|
ASSERT_EQ(OB_SUCCESS, ObIOManager::get_instance().set_io_config(config));
|
|
|
|
preapre_stress(2);
|
|
prepare_conf(fds_[0], 0, 1, 0);
|
|
sleep(10);
|
|
set_no_wait();
|
|
set_io_size(0, 2 * 1024 * 1024);
|
|
start_stress();
|
|
sleep(30);
|
|
stop_stress();
|
|
|
|
// check result
|
|
ASSERT_TRUE(stress_[0].get_fail_count() > 0);
|
|
// ASSERT_TRUE(stress_[0].get_succeed_count() == 0);
|
|
ASSERT_TRUE(stress_[1].get_fail_count() == 0);
|
|
ASSERT_TRUE(stress_[0].get_succeed_count() > 0);
|
|
|
|
// set disk error
|
|
{
|
|
ObDiskGuard guard;
|
|
ASSERT_EQ(OB_SUCCESS, OB_IO_MANAGER.get_disk_manager().get_disk_with_guard(fds_[0], guard));
|
|
guard.get_disk()->diagnose_.record_read_fail(10);
|
|
}
|
|
for (int64_t i = 0; i < DISK_CNT; ++i) {
|
|
// delete disk will clean on going io request
|
|
ASSERT_EQ(OB_SUCCESS, OB_IO_MANAGER.delete_disk(fds_[i]));
|
|
::close(fds_[i]);
|
|
FileDirectoryUtils::delete_file(file_names_[i]);
|
|
}
|
|
sleep(30);
|
|
}
|
|
|
|
} // namespace common
|
|
} // namespace oceanbase
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
oceanbase::common::ObLogger::get_logger().set_log_level("INFO");
|
|
testing::InitGoogleTest(&argc, argv);
|
|
// g++ -shared -o aio_preload.so aio_preload.c -fPIC
|
|
// export LD_PRELOAD="./io/aio_preload.so"
|
|
// return RUN_ALL_TESTS();
|
|
return 0;
|
|
}
|