From 4a68847d02e7610c1203dbe534f1b17ef3a8bccc Mon Sep 17 00:00:00 2001 From: Hanqing Wu Date: Tue, 28 Nov 2023 16:55:46 +0800 Subject: [PATCH] curvebs(client): Fix always get file info from cache Signed-off-by: Hanqing Wu --- src/client/file_instance.cpp | 21 +++ src/client/file_instance.h | 6 +- src/client/libcurve_file.cpp | 2 +- test/client/BUILD | 1 + test/client/file_instance_test.cpp | 153 +++++++++++++++++++++- test/client/mock/mock_namespace_service.h | 11 ++ 6 files changed, 187 insertions(+), 7 deletions(-) diff --git a/src/client/file_instance.cpp b/src/client/file_instance.cpp index 9e709b3114..9e43970fa0 100644 --- a/src/client/file_instance.cpp +++ b/src/client/file_instance.cpp @@ -276,5 +276,26 @@ void FileInstance::StopLease() { } } +FInfo FileInstance::GetCurrentFileInfo(bool force) { + FInfo info = finfo_; + if (!force) { + return info; + } + + FileEpoch fEpoch; + int rc = mdsclient_->GetFileInfo(info.fullPathName, info.userinfo, &info, + &fEpoch); + (void)fEpoch; + if (rc != LIBCURVE_ERROR::OK) { + LOG(WARNING) << "Fail to get current file info from mds, return cached" + "file info, filename: " + << info.fullPathName; + } else { + finfo_ = info; + } + + return info; +} + } // namespace client } // namespace curve diff --git a/src/client/file_instance.h b/src/client/file_instance.h index 9e61394e28..ec52893822 100644 --- a/src/client/file_instance.h +++ b/src/client/file_instance.h @@ -118,12 +118,10 @@ class CURVE_CACHELINE_ALIGNMENT FileInstance { /** * @brief 获取当前instance对应的文件信息 - * + * @param force whether force to get file info from mds * @return 当前instance对应文件的信息 */ - FInfo GetCurrentFileInfo() const { - return finfo_; - } + FInfo GetCurrentFileInfo(bool force = false); static FileInstance* NewInitedFileInstance( const FileServiceOption& fileServiceOption, diff --git a/src/client/libcurve_file.cpp b/src/client/libcurve_file.cpp index 454e463043..132f91c7fe 100644 --- a/src/client/libcurve_file.cpp +++ b/src/client/libcurve_file.cpp @@ -475,7 +475,7 @@ int FileClient::StatFile(int fd, FileStatInfo *finfo) { return -LIBCURVE_ERROR::FAILED; } FileInstance *instance = fileserviceMap_[fd]; - fi = instance->GetCurrentFileInfo(); + fi = instance->GetCurrentFileInfo(/*force=*/true); } BuildFileStatInfo(fi, finfo); diff --git a/test/client/BUILD b/test/client/BUILD index c8aa7a32e3..dc8393e227 100644 --- a/test/client/BUILD +++ b/test/client/BUILD @@ -79,6 +79,7 @@ cc_test( "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", "//test/integration/cluster_common:integration_cluster_common", + "//test/client/mock:curve_client_mock", ], ) diff --git a/test/client/file_instance_test.cpp b/test/client/file_instance_test.cpp index 8718081fc9..59901b000d 100644 --- a/test/client/file_instance_test.cpp +++ b/test/client/file_instance_test.cpp @@ -20,13 +20,22 @@ * Author: wuhanqing */ -#include -#include #include "src/client/file_instance.h" +#include +#include +#include + +#include "test/client/mock/mock_namespace_service.h" + namespace curve { namespace client { +using ::testing::_; +using ::testing::DoAll; +using ::testing::Invoke; +using ::testing::SaveArgPointee; + TEST(FileInstanceTest, CommonTest) { UserInfo userInfo{"test", "passwd"}; std::shared_ptr mdsclient = std::make_shared(); @@ -72,5 +81,145 @@ TEST(FileInstanceTest, IoAlignmentTest) { ASSERT_FALSE(CheckAlign(511, 511, 512)); } +constexpr size_t kMiB = 1 << 20; +constexpr size_t kGiB = 1 << 30; + +class FileInstanceGetFileInfoTest : public ::testing::Test { + protected: + void SetUp() override { + FileServiceOption opts; + opts.metaServerOpt.mdsAddrs = {kSvrAddr}; + + ASSERT_EQ(0, mdsclient_->Initialize(opts.metaServerOpt)); + ASSERT_EQ(0, server_.AddService(&nameService_, + brpc::SERVER_DOESNT_OWN_SERVICE)); + ASSERT_EQ(0, server_.Start(kSvrAddr, nullptr)); + + UserInfo user("test", ""); + instance_.reset(FileInstance::NewInitedFileInstance( + opts, mdsclient_, "/test", user, OpenFlags{}, + /*readonly=*/false)); + + EXPECT_CALL(nameService_, OpenFile(_, _, _, _)) + .WillOnce(Invoke([](::google::protobuf::RpcController* cntl, + const curve::mds::OpenFileRequest*, + curve::mds::OpenFileResponse* response, + google::protobuf::Closure* done) { + response->set_statuscode(curve::mds::StatusCode::kOK); + auto* info = response->mutable_fileinfo(); + info->set_id(2); + info->set_parentid(1); + info->set_chunksize(16ULL * kMiB); + info->set_segmentsize(1ULL * kGiB); + info->set_length(1ULL * kGiB); + auto* session = response->mutable_protosession(); + session->set_sessionid("1"); + session->set_leasetime(60); + session->set_createtime(0); + session->set_sessionstatus( + curve::mds::SessionStatus::kSessionOK); + done->Run(); + })); + + EXPECT_CALL(nameService_, CloseFile(_, _, _, _)) + .WillOnce(Invoke([](::google::protobuf::RpcController* cntl, + const curve::mds::CloseFileRequest*, + curve::mds::CloseFileResponse* response, + google::protobuf::Closure* done) { + response->set_statuscode(curve::mds::StatusCode::kOK); + done->Run(); + })); + + EXPECT_CALL(nameService_, RefreshSession(_, _, _, _)) + .WillRepeatedly( + Invoke([](::google::protobuf::RpcController* cntl, + const curve::mds::ReFreshSessionRequest*, + curve::mds::ReFreshSessionResponse* response, + google::protobuf::Closure* done) { + response->set_statuscode(curve::mds::StatusCode::kOK); + response->set_sessionid(""); + done->Run(); + })); + + ASSERT_EQ(0, instance_->Open()); + } + + void TearDown() override { + ASSERT_EQ(0, instance_->Close()); + + server_.Stop(0); + server_.Join(); + } + + protected: + const char* kSvrAddr = "127.0.0.1:9610"; + + std::shared_ptr mdsclient_ = std::make_shared(); + std::unique_ptr instance_; + + brpc::Server server_; + curve::mds::MockNameService nameService_; +}; + +TEST_F(FileInstanceGetFileInfoTest, TestGetInfoFromCache) { + auto info = instance_->GetCurrentFileInfo(); + ASSERT_EQ(1ULL * kGiB, info.length); +} + +TEST_F(FileInstanceGetFileInfoTest, TestForceGetInfo) { + // get info from mds success, return cached fileinfo + { + EXPECT_CALL(nameService_, GetFileInfo(_, _, _, _)) + .WillOnce(Invoke([](::google::protobuf::RpcController* cntl, + const curve::mds::GetFileInfoRequest*, + curve::mds::GetFileInfoResponse* response, + google::protobuf::Closure* done) { + response->set_statuscode( + curve::mds::StatusCode::kFileNotExists); + done->Run(); + })); + + auto info = instance_->GetCurrentFileInfo(/*force=*/true); + ASSERT_EQ(1ULL * kGiB, info.length); + } + + // get info from mds success, return new fileinfo + { + EXPECT_CALL(nameService_, GetFileInfo(_, _, _, _)) + .WillOnce(Invoke([](::google::protobuf::RpcController* cntl, + const curve::mds::GetFileInfoRequest*, + curve::mds::GetFileInfoResponse* response, + google::protobuf::Closure* done) { + response->set_statuscode(curve::mds::StatusCode::kOK); + auto* info = response->mutable_fileinfo(); + info->set_id(2); + info->set_parentid(1); + info->set_chunksize(16ULL * kMiB); + info->set_segmentsize(1ULL * kGiB); + info->set_length(2ULL * kGiB); // increase file size to 2GiB + done->Run(); + })); + + auto info = instance_->GetCurrentFileInfo(/*force=*/true); + ASSERT_EQ(2ULL * kGiB, info.length); + } + + // get info from mds success, return cached fileinfo + { + EXPECT_CALL(nameService_, GetFileInfo(_, _, _, _)) + .WillOnce(Invoke([](::google::protobuf::RpcController* cntl, + const curve::mds::GetFileInfoRequest*, + curve::mds::GetFileInfoResponse* response, + google::protobuf::Closure* done) { + response->set_statuscode( + curve::mds::StatusCode::kFileNotExists); + done->Run(); + })); + + auto info = instance_->GetCurrentFileInfo(/*force=*/true); + ASSERT_EQ(2ULL * kGiB, info.length); + } +} + } // namespace client } // namespace curve diff --git a/test/client/mock/mock_namespace_service.h b/test/client/mock/mock_namespace_service.h index cfe22f71a3..1c98fa9d27 100644 --- a/test/client/mock/mock_namespace_service.h +++ b/test/client/mock/mock_namespace_service.h @@ -38,6 +38,11 @@ class MockNameService : public CurveFSService { OpenFileResponse* response, google::protobuf::Closure* done)); + MOCK_METHOD4(CloseFile, void(google::protobuf::RpcController* cntl, + const CloseFileRequest* request, + CloseFileResponse* response, + google::protobuf::Closure* done)); + MOCK_METHOD4(DeleteFile, void(google::protobuf::RpcController* cntl, const DeleteFileRequest* request, DeleteFileResponse* response, @@ -64,6 +69,12 @@ class MockNameService : public CurveFSService { const curve::mds::IncreaseFileEpochRequest* request, curve::mds::IncreaseFileEpochResponse* response, ::google::protobuf::Closure* done)); + + MOCK_METHOD4(GetFileInfo, + void(::google::protobuf::RpcController* controller, + const ::curve::mds::GetFileInfoRequest* request, + ::curve::mds::GetFileInfoResponse* response, + ::google::protobuf::Closure* done)); }; } // namespace mds