blob: 2bb37817f9bc572c618327d05b5df9d794b388a2 [file] [log] [blame]
/*
* 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 <gtest/gtest.h>
#include "utils/fail_point.h"
#include "utils/fmt_logging.h"
#include "replica/test/replica_test_base.h"
namespace dsn {
namespace replication {
class replica_disk_test_base : public replica_test_base
{
public:
// create `dir_nodes_count`(tag_1~tag_5) mock disk:
// capacity info
// node_disk disk_capacity disk_available_mb disk_available_ratio
// tag_1 100*5 50*1 10%
// tag_2 100*5 50*2 20%
// tag_3 100*5 50*3 30%
// tag_4 100*5 50*4 40%
// tag_5 100*5 50*5 50%
// total 2500 750 30%
// replica info, for example:
// dir_node primary/secondary
//
// tag_empty_1
// tag_1 1.1 | 1.2,1.3
// 2.1,2.2 | 2.3,2.4,2.5,2.6
//
// tag_2 1.4 | 1.5,1.6
// 2.7,2.8 | 2.9,2.10,2.11,2.12,2.13
// ...
// ...
replica_disk_test_base()
{
fail::setup();
fail::cfg("update_disk_stat", "return()");
generate_mock_app_info();
stub->_fs_manager._dir_nodes.clear();
stub->_fs_manager.reset_disk_stat();
generate_mock_dir_nodes(dir_nodes_count);
generate_mock_empty_dir_node(empty_dir_nodes_count);
stub->generate_replicas_base_dir_nodes_for_app(
app_info_1, app_id_1_primary_count_for_disk, app_id_1_secondary_count_for_disk);
stub->generate_replicas_base_dir_nodes_for_app(
app_info_2, app_id_2_primary_count_for_disk, app_id_2_secondary_count_for_disk);
stub->on_disk_stat();
}
~replica_disk_test_base() { fail::teardown(); }
void generate_mock_dir_node(const app_info &app,
const gpid pid,
const std::string &tag,
const std::string &full_dir = "full_dir")
{
dir_node *node_disk = new dir_node(tag, full_dir);
node_disk->holding_replicas[app.app_id].emplace(pid);
stub->_fs_manager._dir_nodes.emplace_back(node_disk);
}
void remove_mock_dir_node(const std::string &tag)
{
for (auto iter = stub->_fs_manager._dir_nodes.begin();
iter != stub->_fs_manager._dir_nodes.end();
iter++) {
if ((*iter)->tag == tag) {
stub->_fs_manager._dir_nodes.erase(iter);
break;
}
}
}
void update_node_status(const std::shared_ptr<dir_node> &dn,
disk_status::type old_status,
disk_status::type new_status)
{
for (const auto &pids_of_app : dn->holding_replicas) {
for (const auto &pid : pids_of_app.second) {
replica_ptr rep = stub->get_replica(pid);
ASSERT_NE(nullptr, rep);
rep->set_disk_status(new_status);
}
}
if (old_status != new_status) {
dn->status = new_status;
}
}
void prepare_before_add_new_disk_test(const std::string &create_dir,
const std::string &check_rw)
{
stub->_fs_manager.add_new_dir_node("add_new_exist_disk/replica/reps", "add_new_exist_tag");
std::string dir_name = "add_new_not_empty_disk/replica/reps";
utils::filesystem::create_directory(dir_name);
utils::filesystem::create_file(dir_name + "/test_file");
fail::cfg("filesystem_create_directory", "return(" + create_dir + ")");
fail::cfg("filesystem_check_dir_rw", "return(" + check_rw + ")");
}
void reset_after_add_new_disk_test()
{
stub->_fs_manager._dir_nodes.clear();
dsn::utils::filesystem::remove_path("add_new_not_empty_disk");
}
public:
int empty_dir_nodes_count = 1;
int dir_nodes_count = 5;
dsn::app_info app_info_1;
int app_id_1_primary_count_for_disk = 1;
int app_id_1_secondary_count_for_disk = 2;
dsn::app_info app_info_2;
int app_id_2_primary_count_for_disk = 2;
int app_id_2_secondary_count_for_disk = 4;
private:
void generate_mock_app_info()
{
app_info_1.app_id = 1;
app_info_1.app_name = "disk_test_1";
app_info_1.app_type = "replica";
app_info_1.is_stateful = true;
app_info_1.max_replica_count = 3;
app_info_1.partition_count = 8;
app_info_2.app_id = 2;
app_info_2.app_name = "disk_test_2";
app_info_2.app_type = "replica";
app_info_2.is_stateful = true;
app_info_2.max_replica_count = 3;
app_info_2.partition_count = 16;
}
void generate_mock_empty_dir_node(int num)
{
while (num > 0) {
dir_node *node_disk =
new dir_node(fmt::format("tag_empty_{}", num), fmt::format("./tag_empty_{}", num));
stub->_fs_manager._dir_nodes.emplace_back(node_disk);
utils::filesystem::create_directory(node_disk->full_dir);
num--;
}
}
void generate_mock_dir_nodes(int num)
{
int app_id_1_disk_holding_replica_count =
app_id_1_primary_count_for_disk + app_id_1_secondary_count_for_disk;
int app_id_2_disk_holding_replica_count =
app_id_2_primary_count_for_disk + app_id_2_secondary_count_for_disk;
int app_id_1_partition_index = 1;
int app_id_2_partition_index = 1;
int64_t disk_capacity_mb = num * 100;
int count = 0;
while (count++ < num) {
int64_t disk_available_mb = count * 50;
int disk_available_ratio =
static_cast<int>(std::round((double)100 * disk_available_mb / disk_capacity_mb));
// create one mock dir_node and make sure disk_capacity_mb_ > disk_available_mb_
dir_node *node_disk = new dir_node("tag_" + std::to_string(count),
"./tag_" + std::to_string(count),
disk_capacity_mb,
disk_available_mb,
disk_available_ratio);
stub->_options.data_dirs.push_back(
node_disk->full_dir); // open replica need the options
utils::filesystem::create_directory(node_disk->full_dir);
int app_1_replica_count_per_disk = app_id_1_disk_holding_replica_count;
while (app_1_replica_count_per_disk-- > 0) {
node_disk->holding_replicas[app_info_1.app_id].emplace(
gpid(app_info_1.app_id, app_id_1_partition_index++));
}
int app_2_replica_count_per_disk = app_id_2_disk_holding_replica_count;
while (app_2_replica_count_per_disk-- > 0) {
node_disk->holding_replicas[app_info_2.app_id].emplace(
gpid(app_info_2.app_id, app_id_2_partition_index++));
}
stub->_fs_manager._dir_nodes.emplace_back(node_disk);
}
}
};
} // namespace replication
} // namespace dsn