forked from caoXF/curve
765 lines
30 KiB
C++
765 lines
30 KiB
C++
/*
|
|
* Copyright (c) 2020 NetEase Inc.
|
|
*
|
|
* Licensed 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.
|
|
*/
|
|
|
|
/*
|
|
* Project: curve
|
|
* Created Date: Mon Apr 27th 2019
|
|
* Author: lixiaocui
|
|
*/
|
|
|
|
#include "src/chunkserver/trash.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "src/chunkserver/copyset_node.h"
|
|
#include "test/chunkserver/datastore/mock_file_pool.h"
|
|
#include "test/fs/mock_local_filesystem.h"
|
|
|
|
using ::testing::_;
|
|
using ::testing::DoAll;
|
|
using ::testing::ElementsAre;
|
|
using ::testing::Ge;
|
|
using ::testing::Gt;
|
|
using ::testing::Mock;
|
|
using ::testing::NotNull;
|
|
using ::testing::Return;
|
|
using ::testing::ReturnArg;
|
|
using ::testing::SaveArg;
|
|
using ::testing::SetArgPointee;
|
|
using ::testing::SetArrayArgument;
|
|
using ::testing::Truly;
|
|
|
|
using curve::fs::MockLocalFileSystem;
|
|
|
|
namespace curve {
|
|
namespace chunkserver {
|
|
class TrashTest : public ::testing::Test {
|
|
protected:
|
|
void SetUp() {
|
|
lfs = std::make_shared<MockLocalFileSystem>();
|
|
pool = std::make_shared<MockFilePool>(lfs);
|
|
walPool = std::make_shared<MockFilePool>(lfs);
|
|
ops.localFileSystem = lfs;
|
|
ops.chunkFilePool = pool;
|
|
ops.walPool = walPool;
|
|
ops.trashPath = "local://./runlog/trash_test0/trash";
|
|
ops.expiredAfterSec = 1;
|
|
ops.scanPeriodSec = 1;
|
|
|
|
trash = std::make_shared<Trash>();
|
|
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash", _))
|
|
.WillOnce(Return(0));
|
|
trash->Init(ops);
|
|
ASSERT_EQ(0, trash->GetChunkNum());
|
|
}
|
|
|
|
public:
|
|
void RecycleCopyset50Times() {
|
|
EXPECT_CALL(*lfs, DirExists(_)).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*lfs, Mkdir(_)).WillRepeatedly(Return(0));
|
|
EXPECT_CALL(*lfs, Rename(_, _, 0)).WillRepeatedly(Return(0));
|
|
for (int i = 0; i < 50; i++) {
|
|
ASSERT_EQ(0, trash->RecycleCopySet(
|
|
"./runlog/trash_test0/copysets/12345678"));
|
|
}
|
|
}
|
|
|
|
void CleanFiles() {
|
|
std::vector<std::string> files{"12345678"};
|
|
std::string trashPath = "./runlog/trash_test0/trash";
|
|
std::string copysetDir = "./runlog/trash_test0/trash/12345678";
|
|
std::vector<std::string> raftfiles{
|
|
RAFT_LOG_DIR, RAFT_SNAP_DIR, RAFT_META_DIR, RAFT_DATA_DIR, "hello"};
|
|
std::string log = copysetDir + RAFT_LOG_DIR;
|
|
std::string snap = copysetDir + RAFT_SNAP_DIR;
|
|
std::string meta = copysetDir + RAFT_META_DIR;
|
|
std::string data = copysetDir + RAFT_DATA_DIR;
|
|
std::vector<std::string> chunks{"chunk_123", "chunk_345"};
|
|
std::string chunks1 = data + chunks[0];
|
|
std::string chunks2 = data + chunks[1];
|
|
EXPECT_CALL(*lfs, DirExists(trashPath)).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*lfs, List(trashPath, _))
|
|
.WillRepeatedly(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, List(copysetDir, _))
|
|
.WillRepeatedly(DoAll(SetArgPointee<1>(raftfiles), Return(0)));
|
|
EXPECT_CALL(*lfs, Open(copysetDir, _)).WillRepeatedly(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillRepeatedly(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillRepeatedly(Return(0));
|
|
EXPECT_CALL(*lfs, Delete(log)).WillRepeatedly(Return(0));
|
|
EXPECT_CALL(*lfs, Delete(snap)).WillRepeatedly(Return(0));
|
|
EXPECT_CALL(*lfs, Delete(meta)).WillRepeatedly(Return(-1));
|
|
EXPECT_CALL(*lfs, List(data, _))
|
|
.WillRepeatedly(DoAll(SetArgPointee<1>(chunks), Return(0)));
|
|
EXPECT_CALL(*pool, RecycleFile(chunks1)).WillRepeatedly(Return(-1));
|
|
EXPECT_CALL(*pool, RecycleFile(chunks2)).WillRepeatedly(Return(0));
|
|
for (int i = 0; i < 50; i++) {
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
}
|
|
|
|
void SetCopysetNeedDelete(const std::string& copysetdir, bool needDelete) {
|
|
int fd = needDelete ? 1 : 2;
|
|
EXPECT_CALL(*lfs, Open(copysetdir, _)).WillOnce(Return(fd));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
if (needDelete) {
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
}
|
|
EXPECT_CALL(*lfs, Fstat(fd, _))
|
|
.WillRepeatedly(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(fd)).WillRepeatedly(Return(0));
|
|
}
|
|
|
|
protected:
|
|
std::shared_ptr<Trash> trash;
|
|
std::shared_ptr<MockLocalFileSystem> lfs;
|
|
std::shared_ptr<MockFilePool> pool;
|
|
std::shared_ptr<MockFilePool> walPool;
|
|
TrashOptions ops;
|
|
};
|
|
|
|
TEST_F(TrashTest, test_trashDir_not_exist) {
|
|
EXPECT_CALL(*lfs, DirExists(_)).WillOnce(Return(false));
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_list_trashPath_err) {
|
|
EXPECT_CALL(*lfs, DirExists(_)).WillOnce(Return(true));
|
|
EXPECT_CALL(*lfs, List(_, _)).WillOnce(Return(-1));
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_copysetDir_open_fail) {
|
|
std::vector<std::string> files{"hello", "4294967493.55555", "2234"};
|
|
EXPECT_CALL(*lfs, DirExists(_)).WillOnce(Return(true));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(-1));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_copysetDir_stat_err) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
EXPECT_CALL(*lfs, DirExists(_)).WillOnce(Return(true));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
EXPECT_CALL(*lfs, Fstat(10, _)).WillOnce(Return(-1));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_copysetDir_timeNotEnough) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
EXPECT_CALL(*lfs, DirExists(_)).WillOnce(Return(true));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_cleanCopySet_list_err) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
EXPECT_CALL(*lfs, DirExists(_)).Times(2).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)))
|
|
.WillOnce(Return(-1));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_cleanCopySet_list_empty_delete_err) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
EXPECT_CALL(*lfs, DirExists(_)).Times(2).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)))
|
|
.WillOnce(
|
|
DoAll(SetArgPointee<1>(std::vector<std::string>{}), Return(0)));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.WillOnce(Return(-1));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_cleanCopySet_list_empty_delete_success) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
EXPECT_CALL(*lfs, DirExists(_)).Times(2).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)))
|
|
.WillOnce(
|
|
DoAll(SetArgPointee<1>(std::vector<std::string>{}), Return(0)));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.WillOnce(Return(0));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_cleanCopySet_list_noEmpty_recycleChunks_list_err) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
std::vector<std::string> raftfiles{RAFT_LOG_DIR, RAFT_SNAP_DIR,
|
|
RAFT_META_DIR, RAFT_DATA_DIR, "hello"};
|
|
std::vector<std::string> empty;
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.WillOnce(Return(-1));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(raftfiles), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/log", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/data", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/raft_snapshot", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs, List("./runlog/trash_test0/trash/4294967493.55555/raft_meta", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest,
|
|
test_cleanCopySet_list_noEmpty_recycleChunks_list_empty_deleteOk) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
std::vector<std::string> raftfiles{RAFT_LOG_DIR, RAFT_SNAP_DIR,
|
|
RAFT_META_DIR, RAFT_DATA_DIR, "hello"};
|
|
std::vector<std::string> empty;
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(raftfiles), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/log", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/data", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/raft_snapshot", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs, List("./runlog/trash_test0/trash/4294967493.55555/raft_meta", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest,
|
|
test_cleanCopySet_list_noEmpty_recycleChunks_validFile_recycle) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
std::vector<std::string> raftfiles{RAFT_LOG_DIR, RAFT_SNAP_DIR,
|
|
RAFT_META_DIR, RAFT_DATA_DIR, "hello"};
|
|
std::vector<std::string> chunks{"chunk_123", "chunk_345"};
|
|
std::vector<std::string> empty;
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(raftfiles), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/log", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/data", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(chunks), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/raft_snapshot", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs, List("./runlog/trash_test0/trash/4294967493.55555/raft_meta", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
|
|
EXPECT_CALL(
|
|
*pool,
|
|
RecycleFile(
|
|
"./runlog/trash_test0/trash/4294967493.55555/data/chunk_123"))
|
|
.WillOnce(Return(0));
|
|
EXPECT_CALL(
|
|
*pool,
|
|
RecycleFile(
|
|
"./runlog/trash_test0/trash/4294967493.55555/data/chunk_345"))
|
|
.WillOnce(Return(0));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, recycle_wal_success) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
std::vector<std::string> raftfiles{RAFT_LOG_DIR, RAFT_SNAP_DIR,
|
|
RAFT_META_DIR, RAFT_DATA_DIR, "hello"};
|
|
std::vector<std::string> logfiles{
|
|
"curve_log_10086_10087", "curve_log_inprogress_10088",
|
|
"log_10083_10084", "log_inprogress_10085"};
|
|
std::vector<std::string> empty;
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(raftfiles), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/log", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(logfiles), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/data", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/raft_snapshot", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs, List("./runlog/trash_test0/trash/4294967493.55555/raft_meta", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
|
|
EXPECT_CALL(*walPool,
|
|
RecycleFile("./runlog/trash_test0/trash/4294967493.55555/log/"
|
|
"curve_log_10086_10087"))
|
|
.WillOnce(Return(0));
|
|
EXPECT_CALL(*walPool,
|
|
RecycleFile("./runlog/trash_test0/trash/4294967493.55555/log/"
|
|
"curve_log_inprogress_10088"))
|
|
.WillOnce(Return(0));
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, recycle_wal_failed) {
|
|
std::vector<std::string> files{"4294967493.55555"};
|
|
std::vector<std::string> raftfiles{RAFT_LOG_DIR, RAFT_SNAP_DIR,
|
|
RAFT_META_DIR, RAFT_DATA_DIR, "hello"};
|
|
std::vector<std::string> logfiles{
|
|
"curve_log_10086_10087", "curve_log_inprogress_10088",
|
|
"log_10083_10084", "log_inprogress_10085"};
|
|
std::vector<std::string> empty;
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Open("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(Return(10));
|
|
struct stat info;
|
|
time(&info.st_ctime);
|
|
info.st_ctime -= ops.expiredAfterSec * 2 * 3600;
|
|
EXPECT_CALL(*lfs, Fstat(10, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(info), Return(0)));
|
|
EXPECT_CALL(*lfs, Close(10)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(files), Return(0)));
|
|
EXPECT_CALL(*lfs, List("./runlog/trash_test0/trash/4294967493.55555", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(raftfiles), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/log", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(logfiles), Return(0)));
|
|
EXPECT_CALL(*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/data", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs,
|
|
List("./runlog/trash_test0/trash/4294967493.55555/raft_snapshot", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
EXPECT_CALL(
|
|
*lfs, List("./runlog/trash_test0/trash/4294967493.55555/raft_meta", _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(empty), Return(0)));
|
|
|
|
EXPECT_CALL(*walPool,
|
|
RecycleFile("./runlog/trash_test0/trash/4294967493.55555/log/"
|
|
"curve_log_10086_10087"))
|
|
.WillOnce(Return(0));
|
|
EXPECT_CALL(*walPool,
|
|
RecycleFile("./runlog/trash_test0/trash/4294967493.55555/log/"
|
|
"curve_log_inprogress_10088"))
|
|
.WillOnce(Return(-1));
|
|
|
|
// 失败的情况下不应删除
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.Times(0);
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
}
|
|
|
|
TEST_F(TrashTest, recycle_copyset_dir_noExist_createErr) {
|
|
std::string dirPath = "./runlog/trash_test0/copysets/12345678";
|
|
std::string trashPath = "./runlog/trash_test0/trash";
|
|
EXPECT_CALL(*lfs, DirExists(trashPath)).WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Mkdir(trashPath)).WillOnce(Return(-1));
|
|
ASSERT_EQ(-1, trash->RecycleCopySet(dirPath));
|
|
}
|
|
|
|
TEST_F(TrashTest, recycle_copyset_dir_trash_exist) {
|
|
std::string dirPath = "./runlog/trash_test0/copysets/12345678";
|
|
std::string trashPath = "./runlog/trash_test0/trash";
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(*lfs, Mkdir(trashPath)).WillOnce(Return(0));
|
|
ASSERT_EQ(-1, trash->RecycleCopySet(dirPath));
|
|
}
|
|
|
|
TEST_F(TrashTest, recycle_copyset_dir_rename_err) {
|
|
std::string dirPath = "./runlog/trash_test0/copysets/12345678";
|
|
std::string trashPath = "./runlog/trash_test0/trash";
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Mkdir(trashPath)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Rename(dirPath, _, 0)).WillOnce(Return(-1));
|
|
ASSERT_EQ(-1, trash->RecycleCopySet(dirPath));
|
|
}
|
|
|
|
TEST_F(TrashTest, recycle_copyset_dir_list_err) {
|
|
std::string dirPath = "./runlog/trash_test0/copysets/12345678";
|
|
std::string trashPath = "./runlog/trash_test0/trash";
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Mkdir(trashPath)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Rename(dirPath, _, 0)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(Return(-1));
|
|
ASSERT_EQ(0, trash->RecycleCopySet(dirPath));
|
|
}
|
|
|
|
TEST_F(TrashTest, recycle_copyset_dir_ok) {
|
|
std::string dirPath = "./runlog/trash_test0/copysets/12345678";
|
|
std::string trashPath = "./runlog/trash_test0/trash";
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*lfs, Mkdir(trashPath)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, Rename(dirPath, _, 0)).WillOnce(Return(0));
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(Return(0));
|
|
ASSERT_EQ(0, trash->RecycleCopySet(dirPath));
|
|
}
|
|
|
|
TEST_F(TrashTest, DISABLED_test_concurrenct) {
|
|
std::thread thread1(&TrashTest::RecycleCopyset50Times, this);
|
|
std::thread thread2(&TrashTest::CleanFiles, this);
|
|
thread1.join();
|
|
thread2.join();
|
|
}
|
|
|
|
TEST_F(TrashTest, test_chunk_num_statistic) {
|
|
std::string trashPath = "./runlog/trash_test0/trash";
|
|
std::vector<std::string> copysets{"4294967493.55555", "4294967494.55555"};
|
|
std::vector<std::string> dirs{"data", "log"};
|
|
std::vector<std::string> chunks1{"chunk_100", "chunk_101"};
|
|
std::vector<std::string> chunks2{"chunk_200_snap_1", "abc"};
|
|
std::vector<std::string> logfiles1{
|
|
"curve_log_10086_10087", "curve_log_inprogress_10088",
|
|
"log_10083_10084", "log_inprogress_10085"};
|
|
std::vector<std::string> logfiles2{};
|
|
|
|
// (1) chunk exists when init
|
|
// trash/
|
|
// 4294967493.55555/
|
|
// data/
|
|
// chunk_100, chunk_101 +2
|
|
// log/
|
|
// curve_log_10086_10087, +1
|
|
// curve_log_inprogress_10088, +1
|
|
// log_10083_10084,
|
|
// log_inprogress_10085
|
|
// 4294967494.55555/
|
|
// data/
|
|
// chunk_200_snap_1, abc +1
|
|
// log/
|
|
|
|
using item4list = struct{
|
|
std::string subdir;
|
|
std::vector<std::string>& names;
|
|
};
|
|
std::vector<item4list> action4List{
|
|
{ "", copysets },
|
|
{ "/4294967493.55555", dirs},
|
|
{ "/4294967493.55555/data", chunks1 },
|
|
{ "/4294967493.55555/log", logfiles1 },
|
|
{ "/4294967494.55555", dirs},
|
|
{ "/4294967494.55555/data", chunks2 },
|
|
{ "/4294967494.55555/log", logfiles2 },
|
|
};
|
|
|
|
for (auto& it : action4List) {
|
|
EXPECT_CALL(*lfs, List(trashPath + it.subdir, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(it.names), Return(0)));
|
|
}
|
|
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(true)) // data
|
|
.WillOnce(Return(false)) // chunk_100
|
|
.WillOnce(Return(false)) // chunk_101
|
|
.WillOnce(Return(true)) // log
|
|
.WillOnce(Return(false)) // curve_log_10086_10087
|
|
.WillOnce(Return(false)) // curve_log_inprogress_10088_10088
|
|
.WillOnce(Return(false)) // log_10083_10084
|
|
.WillOnce(Return(false)) // log_inprogress_10085
|
|
.WillOnce(Return(true)) // data
|
|
.WillOnce(Return(false)) // chunk_200_snap_1
|
|
.WillOnce(Return(false)) // abc
|
|
.WillOnce(Return(true)); // log
|
|
|
|
trash->Init(ops);
|
|
ASSERT_EQ(5, trash->GetChunkNum());
|
|
|
|
// (2) recycle copyset
|
|
// trash_test0/copysets/4294967495/
|
|
// data/
|
|
// chunk_333, chunk_444 +2
|
|
// log/
|
|
// curve_log_10086_10087 +1
|
|
// raft_snapshot/temp/data/
|
|
// chunk_10000 +1
|
|
//
|
|
std::string copysetDir = "/copysets/4294967495";
|
|
std::vector<std::string> dirs2{"data", "log", "raft_snapshot"};
|
|
EXPECT_CALL(*lfs, DirExists(_))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true)) // data
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true)) // log
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true)) // raft_snapshot
|
|
.WillOnce(Return(true)) // temp
|
|
.WillOnce(Return(true)) // data
|
|
.WillOnce(Return(false));
|
|
|
|
std::string trashedCopysetDir = "/trash_test0/copysets/4294967495";
|
|
EXPECT_CALL(*lfs, Rename(copysetDir, _, 0))
|
|
.WillOnce(DoAll(SaveArg<1>(&trashedCopysetDir), Return(0)));
|
|
std::vector<std::string> chunks3{"chunk_333", "chunk_444"};
|
|
std::vector<std::string> logfiles3{"curve_log_10086_10087"};
|
|
std::vector<std::string> temp{"temp"};
|
|
std::vector<std::string> data{"data"};
|
|
std::vector<std::string> chunks4{"chunk_10000"};
|
|
EXPECT_CALL(*lfs, List(_, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(dirs2), Return(0)))
|
|
.WillOnce(DoAll(SetArgPointee<1>(chunks3), Return(0)))
|
|
.WillOnce(DoAll(SetArgPointee<1>(logfiles3), Return(0)))
|
|
.WillOnce(DoAll(SetArgPointee<1>(temp), Return(0)))
|
|
.WillOnce(DoAll(SetArgPointee<1>(data), Return(0)))
|
|
.WillOnce(DoAll(SetArgPointee<1>(chunks4), Return(0)));
|
|
ASSERT_EQ(0, trash->RecycleCopySet(copysetDir));
|
|
ASSERT_EQ(9, trash->GetChunkNum());
|
|
|
|
// (3) delete eligible copyset
|
|
std::string trashedCopysetName =
|
|
trashedCopysetDir.substr(trashedCopysetDir.find_last_of("/") + 1);
|
|
copysets.push_back(trashedCopysetName);
|
|
|
|
bool needDelete = true;
|
|
bool notNeedDelete = false;
|
|
std::vector<std::string> raftfiles{RAFT_DATA_DIR, RAFT_LOG_DIR};
|
|
|
|
// DirExists
|
|
using item4dirExists = struct{
|
|
std::string subdir;
|
|
bool exist;
|
|
};
|
|
std::vector<item4dirExists> action4DirExists{
|
|
{ "", true },
|
|
{ "/4294967493.55555", true },
|
|
{ "/4294967493.55555/data", true },
|
|
{ "/4294967493.55555/log", true },
|
|
{ "/4294967493.55555/data/chunk_100", false },
|
|
{ "/4294967493.55555/data/chunk_101", false },
|
|
{ "/4294967493.55555/log/curve_log_10086_10087", false },
|
|
{ "/4294967493.55555/log/curve_log_inprogress_10088", false },
|
|
{ "/4294967493.55555/log/log_10083_10084", false },
|
|
{ "/4294967493.55555/log/log_inprogress_10085", false },
|
|
};
|
|
|
|
for (auto& it : action4DirExists) {
|
|
EXPECT_CALL(*lfs, DirExists(trashPath + it.subdir))
|
|
.WillOnce(Return(it.exist));
|
|
}
|
|
|
|
// List
|
|
std::vector<item4list> action4List2{
|
|
{ "", copysets },
|
|
{ "/4294967493.55555", raftfiles },
|
|
{ "/4294967493.55555/data", chunks1 },
|
|
{ "/4294967493.55555/log", logfiles1 },
|
|
};
|
|
|
|
for (auto& it : action4List2) {
|
|
EXPECT_CALL(*lfs, List(trashPath + it.subdir, _))
|
|
.WillOnce(DoAll(SetArgPointee<1>(it.names), Return(0)));
|
|
}
|
|
|
|
SetCopysetNeedDelete(trashPath + "/" + copysets[0], needDelete);
|
|
SetCopysetNeedDelete(trashPath + "/" + copysets[1], notNeedDelete);
|
|
SetCopysetNeedDelete(trashPath + "/" + copysets[2], notNeedDelete);
|
|
|
|
// RecycleFile
|
|
using item4CycleFile = struct{
|
|
std::shared_ptr<MockFilePool> pool;
|
|
std::string subdir;
|
|
int ret;
|
|
};
|
|
std::vector<item4CycleFile> action4CycleFile{
|
|
{ pool, "/4294967493.55555/data/chunk_100", 0 },
|
|
{ pool, "/4294967493.55555/data/chunk_101", -1 },
|
|
{ walPool, "/4294967493.55555/log/curve_log_10086_10087", 0 },
|
|
{ walPool, "/4294967493.55555/log/curve_log_inprogress_10088", -1 },
|
|
};
|
|
|
|
for (auto& it : action4CycleFile) {
|
|
EXPECT_CALL(*(it.pool), RecycleFile(trashPath + it.subdir))
|
|
.WillOnce(Return(it.ret));
|
|
}
|
|
|
|
// Delete
|
|
EXPECT_CALL(*lfs, Delete("./runlog/trash_test0/trash/4294967493.55555"))
|
|
.Times(0);
|
|
|
|
trash->DeleteEligibleFileInTrash();
|
|
ASSERT_EQ(7, trash->GetChunkNum());
|
|
}
|
|
|
|
} // namespace chunkserver
|
|
} // namespace curve
|