From f40f64184b2ec1439dab666506821c88dc989a46 Mon Sep 17 00:00:00 2001 From: Cyber-SiKu Date: Sat, 26 Aug 2023 14:01:30 +0800 Subject: [PATCH] [feat]curvefs/client:support warmup sym link add feat support symlink by fuseOpReadLink Signed-off-by: Cyber-SiKu --- curvefs/src/client/fuse_client.cpp | 2 +- curvefs/src/client/fuse_s3_client.h | 6 +- curvefs/src/client/warmup/warmup_manager.cpp | 191 ++- curvefs/src/client/warmup/warmup_manager.h | 57 +- curvefs/test/client/test_fuse_s3_client.cpp | 1494 ++++++++++++++++-- 5 files changed, 1536 insertions(+), 214 deletions(-) diff --git a/curvefs/src/client/fuse_client.cpp b/curvefs/src/client/fuse_client.cpp index b67d0faa66..19ad5986cf 100644 --- a/curvefs/src/client/fuse_client.cpp +++ b/curvefs/src/client/fuse_client.cpp @@ -1335,7 +1335,6 @@ CURVEFS_ERROR FuseClient::FuseOpLink(fuse_req_t req, CURVEFS_ERROR FuseClient::FuseOpReadLink(fuse_req_t req, fuse_ino_t ino, std::string *linkStr) { (void)req; - VLOG(1) << "FuseOpReadLink, ino: " << ino << ", linkStr: " << linkStr; InodeAttr attr; CURVEFS_ERROR ret = inodeManager_->GetInodeAttr(ino, &attr); if (ret != CURVEFS_ERROR::OK) { @@ -1344,6 +1343,7 @@ CURVEFS_ERROR FuseClient::FuseOpReadLink(fuse_req_t req, fuse_ino_t ino, return ret; } *linkStr = attr.symlink(); + VLOG(1) << "FuseOpReadLink, ino: " << ino << ", linkStr: " << *linkStr; return CURVEFS_ERROR::OK; } diff --git a/curvefs/src/client/fuse_s3_client.h b/curvefs/src/client/fuse_s3_client.h index 68d7bf5d08..bf54c151a0 100644 --- a/curvefs/src/client/fuse_s3_client.h +++ b/curvefs/src/client/fuse_s3_client.h @@ -57,9 +57,13 @@ class FuseS3Client : public FuseClient { char *buffer, size_t *rSize) { return FuseOpRead(req, ino, size, off, fi, buffer, rSize); }; + auto readLinkFunc = [this](fuse_req_t req, fuse_ino_t ino, + std::string *linkStr) { + return FuseClient::FuseOpReadLink(req, ino, linkStr); + }; warmupManager_ = std::make_shared( metaClient_, inodeManager_, dentryManager_, fsInfo_, readFunc, - s3Adaptor_, nullptr); + readLinkFunc, nullptr, s3Adaptor_); } FuseS3Client(const std::shared_ptr &mdsClient, diff --git a/curvefs/src/client/warmup/warmup_manager.cpp b/curvefs/src/client/warmup/warmup_manager.cpp index e135231ab0..9a47c9f5ba 100644 --- a/curvefs/src/client/warmup/warmup_manager.cpp +++ b/curvefs/src/client/warmup/warmup_manager.cpp @@ -24,12 +24,14 @@ #include #include +#include #include #include #include #include #include +#include #include #include "curvefs/src/client/common/common.h" @@ -57,7 +59,7 @@ bool WarmupManagerS3Impl::AddWarmupFilelist(fuse_ino_t key, } // add warmup Progress if (AddWarmupProcess(key, type)) { - VLOG(9) << "add warmup list task:" << key; + LOG(INFO) << "add warmup list task:" << key; WriteLockGuard lock(warmupFilelistDequeMutex_); auto iter = FindWarmupFilelistByKeyLocked(key); if (iter == warmupFilelistDeque_.end()) { @@ -83,7 +85,7 @@ bool WarmupManagerS3Impl::AddWarmupFile(fuse_ino_t key, const std::string &path, } // add warmup Progress if (AddWarmupProcess(key, type)) { - VLOG(9) << "add warmup single task:" << key; + LOG(INFO) << "add warmup single task:" << key; FetchDentryEnqueue(key, path); } return true; @@ -164,7 +166,6 @@ void WarmupManagerS3Impl::FetchDentryEnqueue(fuse_ino_t key, void WarmupManagerS3Impl::LookPath(fuse_ino_t key, std::string file) { VLOG(9) << "LookPath start key: " << key << " file: " << file; - std::vector splitPath; // remove enter, newline, blank std::string blanks("\r\n "); file.erase(0, file.find_first_not_of(blanks)); @@ -173,59 +174,35 @@ void WarmupManagerS3Impl::LookPath(fuse_ino_t key, std::string file) { VLOG(9) << "empty path"; return; } - bool isRoot = false; - if (file == "/") { - splitPath.push_back(file); - isRoot = true; - } else { - curve::common::AddSplitStringToResult(file, "/", &splitPath); + + if (!curve::common::StringStartWith(file, "/")) { + LOG(ERROR) << fmt::format("{} isn't absolute path", file); + file.erase(0, 1); } - VLOG(6) << "splitPath size is: " << splitPath.size(); - if (splitPath.size() == 1 && isRoot) { + std::vector splitPath; + curve::common::AddSplitStringToResult(file, "/", &splitPath); + + VLOG(6) << fmt::format("splitPath: {}", fmt::join(splitPath, ",")); + if (splitPath.empty()) { VLOG(9) << "i am root"; auto task = [this, key]() { FetchChildDentry(key, fsInfo_->rootinodeid()); }; AddFetchDentryTask(key, task); return; - } else if (splitPath.size() == 1) { - VLOG(9) << "parent is root: " << fsInfo_->rootinodeid() - << ", path is: " << splitPath[0]; - auto task = [this, key, splitPath]() { - FetchDentry(key, fsInfo_->rootinodeid(), splitPath[0]); - }; - AddFetchDentryTask(key, task); - return; - } else if (splitPath.size() > 1) { // travel path - VLOG(9) << "traverse path start: " << splitPath.size(); - std::string lastName = splitPath.back(); - splitPath.pop_back(); - fuse_ino_t ino = fsInfo_->rootinodeid(); - for (auto iter : splitPath) { - VLOG(9) << "traverse path: " << iter << "ino is: " << ino; - Dentry dentry; - std::string pathName = iter; - CURVEFS_ERROR ret = - dentryManager_->GetDentry(ino, pathName, &dentry); - if (ret != CURVEFS_ERROR::OK) { - if (ret != CURVEFS_ERROR::NOTEXIST) { - LOG(WARNING) - << "dentryManager_ get dentry fail, ret = " << ret - << ", parent inodeid = " << ino << ", name = " << file; - } - VLOG(9) << "FetchDentry error: " << ret; - return; - } - ino = dentry.inodeid(); + } else { + fuse_ino_t parent; + bool result = + GetInodeSubPathParent(fsInfo_->rootinodeid(), splitPath, &parent); + if (!result) { + LOG(ERROR) << "GetInodeSubPathParent fail, path: " << file; + return; } - auto task = [this, key, ino, lastName]() { - FetchDentry(key, ino, lastName); + std::string lastName = splitPath.back(); + auto task = [this, key, parent, lastName]() { + FetchDentry(key, parent, lastName); }; AddFetchDentryTask(key, task); - VLOG(9) << "ino is: " << ino << " lastname is: " << lastName; - return; - } else { - VLOG(3) << "unknown path"; } VLOG(9) << "LookPath start end: " << key << " file: " << file; } @@ -265,7 +242,25 @@ void WarmupManagerS3Impl::FetchDentry(fuse_ino_t key, fuse_ino_t ino, return; } else if (FsFileType::TYPE_SYM_LINK == dentry.type()) { - // skip links + std::string symLink; + CURVEFS_ERROR statusCode = + fuseOpReadLink_(0, dentry.inodeid(), &symLink); + if (statusCode != CURVEFS_ERROR::OK) { + LOG(ERROR) << "readlink fail, inodeid = " << dentry.inodeid() + << ", path = " << file; + return; + } + std::vector splitSymLink; + curve::common::AddSplitStringToResult(symLink, "/", &splitSymLink); + fuse_ino_t parent; + if (!GetInodeSubPathParent(dentry.inodeid(), splitSymLink, &parent)) { + LOG(ERROR) << "GetInodeSubPathParent fail, path: " << symLink; + return; + } + std::string lastName = splitSymLink.back(); + auto task = [this, key, parent, lastName]() { + FetchDentry(key, parent, lastName); + }; } else { VLOG(3) << "unkown, file: " << file << ", ino: " << ino; return; @@ -302,7 +297,26 @@ void WarmupManagerS3Impl::FetchChildDentry(fuse_ino_t key, fuse_ino_t ino) { }; AddFetchDentryTask(key, task); VLOG(9) << "FetchChildDentry: " << dentry.inodeid(); - } else if (FsFileType::TYPE_SYM_LINK == dentry.type()) { // need todo + } else if (FsFileType::TYPE_SYM_LINK == dentry.type()) { + std::string symLink; + CURVEFS_ERROR statusCode = + fuseOpReadLink_(0, dentry.inodeid(), &symLink); + if (statusCode != CURVEFS_ERROR::OK) { + LOG(ERROR) << "readlink fail, inodeid = " << dentry.inodeid(); + continue; + } + std::vector splitSymLink; + curve::common::AddSplitStringToResult(symLink, "/", &splitSymLink); + fuse_ino_t parent; + if (!GetInodeSubPathParent(dentry.inodeid(), splitSymLink, + &parent)) { + LOG(ERROR) << "GetInodeSubPathParent fail, path: " << symLink; + continue; + } + std::string lastName = splitSymLink.back(); + auto task = [this, key, parent, lastName]() { + FetchDentry(key, parent, lastName); + }; } else { VLOG(9) << "unknown type"; } @@ -411,8 +425,8 @@ void WarmupManagerS3Impl::TravelChunk(fuse_ino_t ino, if (!firstBlockFull) { travelStartIndex = blockIndexBegin + 1; auto objectName = curvefs::common::s3util::GenObjName( - chunkid, blockIndexBegin, compaction, - fsId, ino, objectPrefix); + chunkid, blockIndexBegin, compaction, fsId, ino, + objectPrefix); prefetchObjs->push_back( std::make_pair(objectName, firstBlockSize)); } else { @@ -424,8 +438,8 @@ void WarmupManagerS3Impl::TravelChunk(fuse_ino_t ino, ? blockIndexEnd : blockIndexEnd - 1; auto objectName = curvefs::common::s3util::GenObjName( - chunkid, blockIndexEnd, compaction, - fsId, ino, objectPrefix); + chunkid, blockIndexEnd, compaction, fsId, ino, + objectPrefix); // there is no need to care about the order // in which objects are downloaded prefetchObjs->push_back( @@ -539,8 +553,7 @@ bool WarmupManagerS3Impl::ProgressDone(fuse_ino_t key) { bool ret; { ReadLockGuard lockList(warmupFilelistDequeMutex_); - ret = - FindWarmupFilelistByKeyLocked(key) == warmupFilelistDeque_.end(); + ret = FindWarmupFilelistByKeyLocked(key) == warmupFilelistDeque_.end(); } { @@ -600,7 +613,7 @@ void WarmupManagerS3Impl::ScanCleanWarmupProgress() { ReadLockGuard lock(inode2ProgressMutex_); for (auto iter = inode2Progress_.begin(); iter != inode2Progress_.end();) { if (ProgressDone(iter->first)) { - VLOG(9) << "warmup key: " << iter->first << " done!"; + LOG(INFO) << "warmup task: " << iter->first << " done!"; iter = inode2Progress_.erase(iter); } else { ++iter; @@ -719,6 +732,74 @@ void WarmupManager::CollectMetrics(InterfaceMetric *interface, int count, interface->latency << (butil::cpuwide_time_us() - start); } +bool WarmupManagerS3Impl::GetInodeSubPathParent( + fuse_ino_t inode, std::vector subPath, fuse_ino_t *ret) { + if (subPath.empty()) { + return false; + } + + if (subPath.size() == 1) { + *ret = inode; + return true; + } + + fuse_ino_t nextInode; + std::string currentPath = subPath.front(); + if (currentPath == "..") { + std::shared_ptr inodeWrapper; + CURVEFS_ERROR statusCode = inodeManager_->GetInode(inode, inodeWrapper); + if (statusCode != CURVEFS_ERROR::OK) { + LOG(ERROR) << "get inode fail, inodeid = " << inode; + return false; + } + curve::common::UniqueLock lck = inodeWrapper->GetUniqueLock(); + auto parents = inodeWrapper->GetParentLocked(); + if (parents.empty()) { + // out of curvefs + // For example directory /A is symlinked to ../B + LOG(ERROR) << fmt::format( + "out of curvefs, inodeid = {}, subpath = {}", inode, + fmt::join(subPath, "/")); + return false; + } + // only support one parent + nextInode = parents[0]; + } else if (currentPath == ".") { + nextInode = inode; + } else { + Dentry dentry; + CURVEFS_ERROR statusCode = + dentryManager_->GetDentry(inode, currentPath, &dentry); + if (statusCode != CURVEFS_ERROR::OK) { + LOG(ERROR) << "get dentry fail, inodeid = " << inode + << ", path = " << currentPath; + return false; + } + if (dentry.type() == FsFileType::TYPE_SYM_LINK) { + // sym link + std::string symLink; + CURVEFS_ERROR statusCode = + fuseOpReadLink_(0, dentry.inodeid(), &symLink); + if (statusCode != CURVEFS_ERROR::OK) { + LOG(ERROR) << "readlink fail, inodeid = " << inode + << ", path = " << currentPath; + return false; + } + std::vector splitSymLink; + curve::common::AddSplitStringToResult(symLink, "/", &splitSymLink); + subPath.insert(subPath.begin() + 1, splitSymLink.begin(), + splitSymLink.end()); + nextInode = inode; + } else { + nextInode = dentry.inodeid(); + } + } + + return GetInodeSubPathParent( + nextInode, std::vector(subPath.begin() + 1, subPath.end()), + ret); +} + } // namespace warmup } // namespace client } // namespace curvefs diff --git a/curvefs/src/client/warmup/warmup_manager.h b/curvefs/src/client/warmup/warmup_manager.h index afdd28b047..fea510fca9 100644 --- a/curvefs/src/client/warmup/warmup_manager.h +++ b/curvefs/src/client/warmup/warmup_manager.h @@ -100,11 +100,6 @@ class WarmupInodes { std::set readAheadFiles_; }; - -using FuseOpReadFunctionType = - std::function; - class WarmupProgress { public: explicit WarmupProgress(WarmupStorageType type = curvefs::client::common:: @@ -148,9 +143,7 @@ class WarmupProgress { ",finished:" + std::to_string(finished_); } - WarmupStorageType GetStorageType() { - return storageType_; - } + WarmupStorageType GetStorageType() { return storageType_; } private: uint64_t total_; @@ -160,6 +153,14 @@ class WarmupProgress { WarmupStorageType storageType_; }; + +using FuseOpReadFunctionType = + std::function; + +using FuseOpReadLinkFunctionType = + std::function; + class WarmupManager { public: WarmupManager() @@ -176,16 +177,16 @@ class WarmupManager { std::shared_ptr dentryManager, std::shared_ptr fsInfo, FuseOpReadFunctionType readFunc, + FuseOpReadLinkFunctionType readLinkFunc, std::shared_ptr kvClientManager) : mounted_(false), metaClient_(std::move(metaClient)), inodeManager_(std::move(inodeManager)), dentryManager_(std::move(dentryManager)), fsInfo_(std::move(fsInfo)), fuseOpRead_(std::move(readFunc)), + fuseOpReadLink_(std::move(readLinkFunc)), kvClientManager_(std::move(kvClientManager)) {} - virtual void Init(const FuseClientOption &option) { - option_ = option; - } + virtual void Init(const FuseClientOption &option) { option_ = option; } virtual void UnInit() { ClearWarmupProcess(); } virtual bool AddWarmupFilelist(fuse_ino_t key, WarmupStorageType type) = 0; @@ -202,6 +203,10 @@ class WarmupManager { fuseOpRead_ = read; } + void SetFuseOpReadLink(const FuseOpReadLinkFunctionType &readLink) { + fuseOpReadLink_ = readLink; + } + void SetKVClientManager(std::shared_ptr kvClientManager) { kvClientManager_ = std::move(kvClientManager); } @@ -275,6 +280,9 @@ class WarmupManager { // FuseOpRead FuseOpReadFunctionType fuseOpRead_; + // FuseOpReadLink + FuseOpReadLinkFunctionType fuseOpReadLink_; + // warmup progress std::unordered_map inode2Progress_; BthreadRWLock inode2ProgressMutex_; @@ -291,11 +299,13 @@ class WarmupManagerS3Impl : public WarmupManager { std::shared_ptr inodeManager, std::shared_ptr dentryManager, std::shared_ptr fsInfo, FuseOpReadFunctionType readFunc, - std::shared_ptr s3Adaptor, - std::shared_ptr kvClientManager) + FuseOpReadLinkFunctionType readLinkFunc, + std::shared_ptr kvClientManager, + std::shared_ptr s3Adaptor) : WarmupManager(std::move(metaClient), std::move(inodeManager), std::move(dentryManager), std::move(fsInfo), - std::move(readFunc), std::move(kvClientManager)), + std::move(readFunc), std::move(readLinkFunc), + std::move(kvClientManager)), s3Adaptor_(std::move(s3Adaptor)) {} bool AddWarmupFilelist(fuse_ino_t key, WarmupStorageType type) override; @@ -305,7 +315,7 @@ class WarmupManagerS3Impl : public WarmupManager { void Init(const FuseClientOption &option) override; void UnInit() override; - private: + protected: void BackGroundFetch(); void GetWarmupList(const WarmupFilelist &filelist, @@ -315,6 +325,23 @@ class WarmupManagerS3Impl : public WarmupManager { void LookPath(fuse_ino_t key, std::string file); + /** + * @brief Given parent inode id and subpath to get the Dentry. + * If there is a soft link in the middle, + * it will be converted automatically. + * But not check last name + * for example: parent = 1(/a), subPath{b,c}(b/c) then the + * return is the inodeid of /a/b + * + * @param parent + * @param subPath + * @param ret return value + * @return false: subPath isn't belong to inode + */ + bool GetInodeSubPathParent(fuse_ino_t inode, + std::vector subPath, + fuse_ino_t *ret); + void FetchDentry(fuse_ino_t key, fuse_ino_t ino, const std::string &file); void FetchChildDentry(fuse_ino_t key, fuse_ino_t ino); diff --git a/curvefs/test/client/test_fuse_s3_client.cpp b/curvefs/test/client/test_fuse_s3_client.cpp index aeb641badb..d39744cd74 100644 --- a/curvefs/test/client/test_fuse_s3_client.cpp +++ b/curvefs/test/client/test_fuse_s3_client.cpp @@ -23,15 +23,18 @@ #include #include +#include #include #include +#include #include "curvefs/proto/metaserver.pb.h" #include "curvefs/src/client/common/common.h" #include "curvefs/src/client/filesystem/error.h" #include "curvefs/src/client/filesystem/meta.h" #include "curvefs/src/client/fuse_s3_client.h" +#include "curvefs/src/client/inode_wrapper.h" #include "curvefs/src/client/rpcclient/metaserver_client.h" #include "curvefs/src/client/s3/disk_cache_manager_impl.h" #include "curvefs/src/client/warmup/warmup_manager.h" @@ -44,6 +47,7 @@ #include "curvefs/test/client/mock_inode_cache_manager.h" #include "curvefs/test/client/mock_metaserver_client.h" #include "curvefs/test/client/rpcclient/mock_mds_client.h" +#include "fuse3/fuse_lowlevel.h" struct fuse_req { struct fuse_ctx *ctx; @@ -73,9 +77,9 @@ namespace client { using ::curve::common::Configuration; using ::curvefs::mds::topology::PartitionTxId; using ::testing::_; -using ::testing::DoAll; using ::testing::AtLeast; using ::testing::Contains; +using ::testing::DoAll; using ::testing::Invoke; using ::testing::Return; using ::testing::SetArgPointee; @@ -99,6 +103,33 @@ static bool operator==(const Dentry &lhs, const Dentry &rhs) { EQUAL(inodeid) && EQUAL(flag); } +class WarmupManagerS3Test : public warmup::WarmupManagerS3Impl { + public: + WarmupManagerS3Test(std::shared_ptr metaClient, + std::shared_ptr inodeManager, + std::shared_ptr dentryManager, + std::shared_ptr fsInfo, + warmup::FuseOpReadFunctionType readFunc, + warmup::FuseOpReadLinkFunctionType readLinkFunc, + std::shared_ptr kvClientManager, + std::shared_ptr s3Adaptor) + : warmup::WarmupManagerS3Impl( + std::move(metaClient), std::move(inodeManager), + std::move(dentryManager), std::move(fsInfo), std::move(readFunc), + std::move(readLinkFunc), std::move(kvClientManager), + std::move(s3Adaptor)) {} + bool GetInodeSubPathParent(fuse_ino_t inode, + std::vector subPath, + fuse_ino_t *ret) { + return warmup::WarmupManagerS3Impl::GetInodeSubPathParent(inode, + subPath, ret); + } + + void FetchDentry(fuse_ino_t key, fuse_ino_t ino, const std::string &file) { + return warmup::WarmupManagerS3Impl::FetchDentry(key, ino, file); + } +}; + class TestFuseS3Client : public ::testing::Test { protected: TestFuseS3Client() {} @@ -111,9 +142,9 @@ class TestFuseS3Client : public ::testing::Test { s3ClientAdaptor_ = std::make_shared(); inodeManager_ = std::make_shared(); dentryManager_ = std::make_shared(); - warmupManager_ = std::make_shared( + warmupManager_ = std::make_shared( metaClient_, inodeManager_, dentryManager_, nullptr, nullptr, - s3ClientAdaptor_, nullptr); + nullptr, nullptr, s3ClientAdaptor_); client_ = std::make_shared( mdsClient_, metaClient_, inodeManager_, dentryManager_, s3ClientAdaptor_, warmupManager_); @@ -124,6 +155,11 @@ class TestFuseS3Client : public ::testing::Test { return client_->FuseOpRead(req, ino, size, off, fi, buffer, rSize); }; warmupManager_->SetFuseOpRead(readFunc); + auto readLinkFunc = [this](fuse_req_t req, fuse_ino_t ino, + std::string *symLink) { + return client_->FuseOpReadLink(req, ino, symLink); + }; + warmupManager_->SetFuseOpReadLink(readLinkFunc); InitOptionBasic(&fuseClientOption_); InitFSInfo(client_); @@ -195,7 +231,7 @@ class TestFuseS3Client : public ::testing::Test { std::shared_ptr client_; FuseClientOption fuseClientOption_; Aws::SDKOptions awsOptions_; - std::shared_ptr warmupManager_; + std::shared_ptr warmupManager_; }; TEST_F(TestFuseS3Client, test_Init_with_KVCache) { @@ -899,12 +935,1234 @@ TEST_F(TestFuseS3Client, warmUp_FetchChildDentry_suc_ListDentry) { ASSERT_FALSE(ret); } +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_empty) { + /* +.(1) parent + */ + fuse_ino_t inode = 0; + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + 0, std::vector(), &inode), + false); +} + +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_1depth) { + /* +.(1) parent +├── A(2) + */ + constexpr fuse_ino_t root = 1; + constexpr fuse_ino_t aInodeid = 2; + fuse_ino_t ret = 0; + + std::string aName = "A"; + Dentry dentry; + dentry.set_fsid(fsId); + dentry.set_name(aName); + dentry.set_parentinodeid(root); + dentry.set_inodeid(aInodeid); + dentry.set_type(FsFileType::TYPE_S3); + + warmupManager_->GetInodeSubPathParent(root, std::vector{aName}, + &ret); + ASSERT_EQ(ret, root); +} + +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_2depth) { + /* +.(1) parent +└── A(2) + ├── B(3) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + + auto GetDentryReplace = + [root, aName, dentryA](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillOnce(Invoke(GetDentryReplace)); + + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, bName}, &ret), + true); + ASSERT_EQ(ret, aInodeid); +} + +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_getDentryFailed) { + /* +.(1) parent +└── A(2) + ├── B(3) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + + auto GetDentryReplace = [](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillOnce(Invoke(GetDentryReplace)); + + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, bName}, &ret), + false); +} + +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_3depth) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ ├──C(4) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryB.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, bName, cName}, &ret), + true); + ASSERT_EQ(ret, bInodeid); +} + +TEST_F(TestFuseS3Client, + warmUp_GetInodeSubPathParent_symLink_getInodeAttrFailed) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> B +│ │ └── D(5) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = [](uint64_t inodeId, + InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, cName, dName}, &ret), + false); +} + +TEST_F(TestFuseS3Client, warmUp_FetchDentry_symLink_getInodeAttrFailed) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> B +│ │ └── D(5) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = [](uint64_t inodeId, + InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + warmupManager_->FetchDentry(123, aInodeid, cName); +} + +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_symLink_1depth) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> B +│ │ └── D(5) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + InodeAttr attrC; + attrC.set_symlink(bName); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = + [cInodeid, attrC](uint64_t inodeId, InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + case cInodeid: + *out = attrC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, cName, dName}, &ret), + true); + ASSERT_EQ(ret, bInodeid); +} + +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_symLink_1depth_1) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> ./B +│ │ └── D(5) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + InodeAttr attrC; + attrC.set_symlink(fmt::format("./{}", bName)); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = + [cInodeid, attrC](uint64_t inodeId, InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + case cInodeid: + *out = attrC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, cName, dName}, &ret), + true); + ASSERT_EQ(ret, bInodeid); +} + +TEST_F(TestFuseS3Client, warmUp_FetchDentry_symLink_1depth_1) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> ./B +│ │ └── D(5) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + InodeAttr attrC; + attrC.set_symlink(fmt::format("./{}", bName)); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = + [cInodeid, attrC](uint64_t inodeId, InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + case cInodeid: + *out = attrC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + warmupManager_->FetchDentry(123, aInodeid, cName); +} + +TEST_F(TestFuseS3Client, + warmUp_GetInodeSubPathParent_symLink_2depth_GetInodeWrapperFailed) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> ../A +│ │ ├── B(3) +│ │ │ └── D(5) +│ │ ├── C(4) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + Inode inodeA; + inodeA.set_fsid(fsId); + inodeA.set_inodeid(aInodeid); + std::shared_ptr inodeWrapperA = + std::make_shared(inodeA, metaClient_); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + InodeAttr attrC; + attrC.set_symlink(fmt::format("../{}", aName)); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = + [cInodeid, attrC](uint64_t inodeId, InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + case cInodeid: + *out = attrC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + auto GetInodeReplace = + [](uint64_t inodeId, + std::shared_ptr &out) -> CURVEFS_ERROR { + switch (inodeId) { + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInode(_, _)) + .WillOnce(Invoke(GetInodeReplace)); + + ASSERT_EQ( + warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, cName, bName, dName}, &ret), + false); +} + +TEST_F(TestFuseS3Client, + warmUp_GetInodeSubPathParent_symLink_2depth_noparents) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> ../A +│ │ ├── B(3) +│ │ │ └── D(5) +│ │ ├── C(4) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + Inode inodeA; + inodeA.set_fsid(fsId); + inodeA.set_inodeid(aInodeid); + std::shared_ptr inodeWrapperA = + std::make_shared(inodeA, metaClient_); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + InodeAttr attrC; + attrC.set_symlink(fmt::format("../{}", aName)); + Inode inodeC; + inodeC.set_fsid(fsId); + inodeC.set_inodeid(cInodeid); + std::shared_ptr inodeWrapperC = + std::make_shared(inodeC, metaClient_); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = + [cInodeid, attrC](uint64_t inodeId, InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + case cInodeid: + *out = attrC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + auto GetInodeReplace = + [aInodeid, inodeWrapperA, cInodeid, + inodeWrapperC](uint64_t inodeId, + std::shared_ptr &out) -> CURVEFS_ERROR { + switch (inodeId) { + case aInodeid: + out = inodeWrapperA; + return CURVEFS_ERROR::OK; + case cInodeid: + out = inodeWrapperC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInode(_, _)) + .WillOnce(Invoke(GetInodeReplace)); + + ASSERT_EQ( + warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, cName, bName, dName}, &ret), + false); +} + +TEST_F(TestFuseS3Client, warmUp_GetInodeSubPathParent_symLink_2depth) { + /* +.(1) parent +└── A(2) +│ ├── B(3) +│ │ └── D(5) +│ ├── C(4) -> ../A +│ │ ├── B(3) +│ │ │ └── D(5) +│ │ ├── C(4) + */ + constexpr fuse_ino_t root = 1; + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + Inode inodeA; + inodeA.set_fsid(fsId); + inodeA.set_inodeid(aInodeid); + inodeA.add_parent(root); + std::shared_ptr inodeWrapperA = + std::make_shared(inodeA, metaClient_); + + std::string bName = "B"; + constexpr fuse_ino_t bInodeid = 3; + Dentry dentryB; + dentryB.set_fsid(fsId); + dentryB.set_name(bName); + dentryB.set_parentinodeid(dentryA.inodeid()); + dentryB.set_inodeid(bInodeid); + dentryB.set_type(FsFileType::TYPE_DIRECTORY); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + InodeAttr attrC; + attrC.set_symlink(fmt::format("../{}", aName)); + Inode inodeC; + inodeC.set_fsid(fsId); + inodeC.set_inodeid(cInodeid); + inodeC.add_parent(aInodeid); + std::shared_ptr inodeWrapperC = + std::make_shared(inodeC, metaClient_); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(dentryB.inodeid()); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = + [root, aName, dentryA, aInodeid, bName, dentryB, bInodeid, cName, + dentryC, dName, dentryD](fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == bName) { + *out = dentryB; + return CURVEFS_ERROR::OK; + } else if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + case bInodeid: + if (name == dName) { + *out = dentryD; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = + [cInodeid, attrC](uint64_t inodeId, InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + case cInodeid: + *out = attrC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + auto GetInodeReplace = + [aInodeid, inodeWrapperA, cInodeid, + inodeWrapperC](uint64_t inodeId, + std::shared_ptr &out) -> CURVEFS_ERROR { + switch (inodeId) { + case aInodeid: + out = inodeWrapperA; + return CURVEFS_ERROR::OK; + case cInodeid: + out = inodeWrapperC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInode(_, _)) + .WillOnce(Invoke(GetInodeReplace)); + + ASSERT_EQ( + warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, cName, bName, dName}, &ret), + true); + ASSERT_EQ(ret, bInodeid); +} + +TEST_F(TestFuseS3Client, + warmUp_GetInodeSubPathParent_symLink_2depth_outcurvefs) { + /* +.(1) root +└── A(2) +│ ├── C(4) -> ../../F +│ │ ├── D(3) + */ + constexpr fuse_ino_t root = 1; + Inode inodeRoot; + inodeRoot.set_fsid(fsId); + inodeRoot.set_inodeid(root); + std::shared_ptr inodeWrapperRoot = + std::make_shared(inodeRoot, metaClient_); + + fuse_ino_t ret = 0; + + std::string aName = "A"; + constexpr fuse_ino_t aInodeid = 2; + Dentry dentryA; + dentryA.set_fsid(fsId); + dentryA.set_name(aName); + dentryA.set_parentinodeid(root); + dentryA.set_inodeid(aInodeid); + dentryA.set_type(FsFileType::TYPE_DIRECTORY); + Inode inodeA; + inodeA.set_fsid(fsId); + inodeA.set_inodeid(aInodeid); + inodeA.add_parent(root); + std::shared_ptr inodeWrapperA = + std::make_shared(inodeA, metaClient_); + + std::string cName = "C"; + constexpr fuse_ino_t cInodeid = 4; + Dentry dentryC; + dentryC.set_fsid(fsId); + dentryC.set_name(cName); + dentryC.set_parentinodeid(dentryA.inodeid()); + dentryC.set_inodeid(cInodeid); + dentryC.set_type(FsFileType::TYPE_SYM_LINK); + InodeAttr attrC; + attrC.set_symlink("../../F"); + Inode inodeC; + inodeC.set_fsid(fsId); + inodeC.set_inodeid(cInodeid); + inodeC.add_parent(aInodeid); + std::shared_ptr inodeWrapperC = + std::make_shared(inodeC, metaClient_); + + std::string dName = "D"; + constexpr fuse_ino_t dInodeid = 5; + Dentry dentryD; + dentryD.set_fsid(fsId); + dentryD.set_name(dName); + dentryD.set_parentinodeid(1234); + dentryD.set_inodeid(dInodeid); + dentryD.set_type(FsFileType::TYPE_DIRECTORY); + + auto GetDentryReplace = [root, aName, dentryA, aInodeid, cName, dentryC]( + fuse_ino_t parent, const std::string &name, + Dentry *out) -> CURVEFS_ERROR { + switch (parent) { + case root: + if (name == aName) { + *out = dentryA; + return CURVEFS_ERROR::OK; + } + break; + case aInodeid: + if (name == cName) { + *out = dentryC; + return CURVEFS_ERROR::OK; + } + break; + default: + return CURVEFS_ERROR::NOTEXIST; + } + return CURVEFS_ERROR::OK; + }; + + EXPECT_CALL(*dentryManager_, GetDentry(_, _, _)) + .WillRepeatedly(Invoke(GetDentryReplace)); + + auto GetInodeAttrReplace = + [cInodeid, attrC](uint64_t inodeId, InodeAttr *out) -> CURVEFS_ERROR { + switch (inodeId) { + case cInodeid: + *out = attrC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInodeAttr(_, _)) + .WillOnce(Invoke(GetInodeAttrReplace)); + + auto GetInodeReplace = + [inodeWrapperRoot, aInodeid, inodeWrapperA, cInodeid, + inodeWrapperC](uint64_t inodeId, + std::shared_ptr &out) -> CURVEFS_ERROR { + switch (inodeId) { + case root: + out = inodeWrapperRoot; + return CURVEFS_ERROR::OK; + case aInodeid: + out = inodeWrapperA; + return CURVEFS_ERROR::OK; + case cInodeid: + out = inodeWrapperC; + return CURVEFS_ERROR::OK; + default: + return CURVEFS_ERROR::NOTEXIST; + } + }; + + EXPECT_CALL(*inodeManager_, GetInode(_, _)) + .WillRepeatedly(Invoke(GetInodeReplace)); + + ASSERT_EQ(warmupManager_->GetInodeSubPathParent( + root, std::vector{aName, cName, dName}, &ret), + false); +} + TEST_F(TestFuseS3Client, FuseInit_when_fs_exist) { MountOption mOpts; memset(&mOpts, 0, sizeof(mOpts)); - mOpts.fsName = const_cast("s3fs"); - mOpts.mountPoint = const_cast("host1:/test"); - mOpts.fsType = const_cast("s3"); + mOpts.fsName = const_cast("s3fs"); + mOpts.mountPoint = const_cast("host1:/test"); + mOpts.fsType = const_cast("s3"); std::string fsName = mOpts.fsName; FsInfo fsInfoExp; @@ -925,9 +2183,9 @@ TEST_F(TestFuseS3Client, FuseInit_when_fs_exist) { TEST_F(TestFuseS3Client, FuseOpDestroy) { MountOption mOpts; memset(&mOpts, 0, sizeof(mOpts)); - mOpts.fsName = const_cast("s3fs"); - mOpts.mountPoint = const_cast("host1:/test"); - mOpts.fsType = const_cast("s3"); + mOpts.fsName = const_cast("s3fs"); + mOpts.mountPoint = const_cast("host1:/test"); + mOpts.fsType = const_cast("s3"); std::string fsName = mOpts.fsName; @@ -1207,32 +2465,24 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_NotEnableSumInDir) { inode.mutable_xattr()->insert({XATTRFBYTES, "0"}); EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgPointee<1>(dlist1), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(dlist1), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetInodeAttr(_, _)) - .WillOnce( - DoAll(SetArgPointee<1>(attrs), Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgPointee<1>(attrs1), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(attrs), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(attrs1), Return(CURVEFS_ERROR::OK))); CURVEFS_ERROR ret = client_->FuseOpGetXattr(req, ino, rname, &value, size); ASSERT_EQ(CURVEFS_ERROR::OK, ret); ASSERT_EQ(value, "4596"); EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetInodeAttr(_, _)) - .WillOnce( - DoAll(SetArgPointee<1>(attrs), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(attrs), Return(CURVEFS_ERROR::OK))); ret = client_->FuseOpGetXattr(req, ino, name, &value, size); ASSERT_EQ(CURVEFS_ERROR::OK, ret); @@ -1281,15 +2531,14 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_NotEnableSumInDir_Failed) { // get inode failed EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce(DoAll(SetArgPointee<1>(inode), - Return(CURVEFS_ERROR::INTERNAL))); + .WillOnce( + DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::INTERNAL))); CURVEFS_ERROR ret = client_->FuseOpGetXattr(req, ino, rname, &value, size); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); // list dentry failed EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) .WillOnce(Return(CURVEFS_ERROR::NOTEXIST)); ret = client_->FuseOpGetXattr(req, ino, rname, &value, size); @@ -1297,11 +2546,9 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_NotEnableSumInDir_Failed) { // BatchGetInodeAttr failed EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetInodeAttr(_, _)) .WillOnce(Return(CURVEFS_ERROR::INTERNAL)); ret = client_->FuseOpGetXattr(req, ino, rname, &value, size); @@ -1356,20 +2603,15 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_EnableSumInDir) { EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) .Times(3) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgPointee<1>(attr), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(attr), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) .WillOnce( DoAll(SetArgPointee<1>(emptyDlist), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetXAttr(_, _)) - .WillOnce( - DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); CURVEFS_ERROR ret = client_->FuseOpGetXattr(req, ino, name, &value, size); ASSERT_EQ(CURVEFS_ERROR::OK, ret); @@ -1431,8 +2673,7 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_EnableSumInDir_Failed) { // AddUllStringToFirst failed EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce(DoAll(SetArgPointee<1>(inode), - Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); ret = client_->FuseOpGetXattr(req, ino, name, &value, size); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); inode.mutable_xattr()->find(XATTRFBYTES)->second = "100"; @@ -1453,8 +2694,7 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_EnableSumInDir_Failed) { .WillRepeatedly( DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) .WillRepeatedly( DoAll(SetArgPointee<1>(emptyDlist), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetXAttr(_, _)) @@ -1469,13 +2709,11 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_EnableSumInDir_Failed) { .WillRepeatedly( DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) .WillRepeatedly( DoAll(SetArgPointee<1>(emptyDlist), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetXAttr(_, _)) - .WillOnce( - DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); ret = client_->FuseOpGetXattr(req, ino, rname, &value, size); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); @@ -1487,13 +2725,11 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_EnableSumInDir_Failed) { .WillRepeatedly( DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) .WillRepeatedly( DoAll(SetArgPointee<1>(emptyDlist), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetXAttr(_, _)) - .WillOnce( - DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); ret = client_->FuseOpGetXattr(req, ino, rname, &value, size); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); @@ -1505,13 +2741,11 @@ TEST_F(TestFuseS3Client, FuseOpGetXattr_EnableSumInDir_Failed) { .WillRepeatedly( DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, ListDentry(_, _, _, _, _)) - .WillOnce( - DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgPointee<1>(dlist), Return(CURVEFS_ERROR::OK))) .WillRepeatedly( DoAll(SetArgPointee<1>(emptyDlist), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*inodeManager_, BatchGetXAttr(_, _)) - .WillOnce( - DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgPointee<1>(xattrs), Return(CURVEFS_ERROR::OK))); ret = client_->FuseOpGetXattr(req, ino, rname, &value, size); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); } @@ -1524,7 +2758,7 @@ TEST_F(TestFuseS3Client, FuseOpCreate_EnableSummary) { fakeReq.ctx = &fakeCtx; fuse_req_t req = &fakeReq; fuse_ino_t parent = 1; - const char* name = "xxx"; + const char *name = "xxx"; mode_t mode = 1; struct fuse_file_info fi; fi.flags = 0; @@ -1555,15 +2789,13 @@ TEST_F(TestFuseS3Client, FuseOpCreate_EnableSummary) { parentInode.mutable_xattr()->insert({XATTRENTRIES, "2"}); parentInode.mutable_xattr()->insert({XATTRFBYTES, "100"}); - auto parentInodeWrapper = std::make_shared( - parentInode, metaClient_); + auto parentInodeWrapper = + std::make_shared(parentInode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(_, _)) - .WillOnce( - DoAll(SetArgReferee<1>(parentInodeWrapper), - Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgReferee<1>(parentInodeWrapper), - Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgReferee<1>(parentInodeWrapper), + Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgReferee<1>(parentInodeWrapper), + Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttrWithOutNlink(_, _, _, _, _)) .WillRepeatedly(Return(MetaStatusCode::OK)); @@ -1572,8 +2804,8 @@ TEST_F(TestFuseS3Client, FuseOpCreate_EnableSummary) { .Times(1); // update mtime directly EntryOut entryOut; - CURVEFS_ERROR ret = client_->FuseOpCreate(req, parent, name, mode, &fi, - &entryOut); + CURVEFS_ERROR ret = + client_->FuseOpCreate(req, parent, name, mode, &fi, &entryOut); ASSERT_EQ(CURVEFS_ERROR::OK, ret); auto p = parentInodeWrapper->GetInodeLocked(); @@ -1588,7 +2820,7 @@ TEST_F(TestFuseS3Client, FuseOpWrite_EnableSummary) { fuse_req_t req = nullptr; fuse_ino_t ino = 1; - const char* buf = "xxx"; + const char *buf = "xxx"; size_t size = 4; off_t off = 0; struct fuse_file_info fi; @@ -1611,18 +2843,15 @@ TEST_F(TestFuseS3Client, FuseOpWrite_EnableSummary) { parentInode.mutable_xattr()->insert({XATTRENTRIES, "1"}); parentInode.mutable_xattr()->insert({XATTRFBYTES, "0"}); - auto parentInodeWrapper = std::make_shared( - parentInode, metaClient_); - EXPECT_CALL(*inodeManager_, ShipToFlush(_)) - .Times(2); + auto parentInodeWrapper = + std::make_shared(parentInode, metaClient_); + EXPECT_CALL(*inodeManager_, ShipToFlush(_)).Times(2); EXPECT_CALL(*inodeManager_, GetInode(_, _)) .WillOnce( DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgReferee<1>(parentInodeWrapper), - Return(CURVEFS_ERROR::OK))); - EXPECT_CALL(*s3ClientAdaptor_, Write(_, _, _, _)) - .WillOnce(Return(size)); + .WillOnce(DoAll(SetArgReferee<1>(parentInodeWrapper), + Return(CURVEFS_ERROR::OK))); + EXPECT_CALL(*s3ClientAdaptor_, Write(_, _, _, _)).WillOnce(Return(size)); FileOut fileOut; CURVEFS_ERROR ret = @@ -1644,7 +2873,7 @@ TEST_F(TestFuseS3Client, FuseOpLink_EnableSummary) { fuse_req_t req = nullptr; fuse_ino_t ino = 1; fuse_ino_t newparent = 2; - const char* newname = "xxxx"; + const char *newname = "xxxx"; Inode inode; inode.set_inodeid(ino); @@ -1671,11 +2900,10 @@ TEST_F(TestFuseS3Client, FuseOpLink_EnableSummary) { .WillRepeatedly(Return(MetaStatusCode::OK)); EXPECT_CALL(*dentryManager_, CreateDentry(_)) .WillOnce(Return(CURVEFS_ERROR::OK)); - EXPECT_CALL(*inodeManager_, ShipToFlush(_)) - .Times(1); + EXPECT_CALL(*inodeManager_, ShipToFlush(_)).Times(1); EntryOut entryOut; - CURVEFS_ERROR ret = client_->FuseOpLink(req, ino, newparent, newname, - &entryOut); + CURVEFS_ERROR ret = + client_->FuseOpLink(req, ino, newparent, newname, &entryOut); ASSERT_EQ(CURVEFS_ERROR::OK, ret); auto p = pinodeWrapper->GetInode(); ASSERT_EQ(p.xattr().find(XATTRFILES)->second, "1"); @@ -1705,7 +2933,7 @@ TEST_F(TestFuseS3Client, FuseOpUnlink_EnableSummary) { .WillOnce(DoAll(SetArgPointee<2>(dentry), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*dentryManager_, - DeleteDentry(parent, name, FsFileType::TYPE_S3)) + DeleteDentry(parent, name, FsFileType::TYPE_S3)) .WillOnce(Return(CURVEFS_ERROR::OK)); Inode inode; @@ -1731,25 +2959,22 @@ TEST_F(TestFuseS3Client, FuseOpUnlink_EnableSummary) { attr.set_inodeid(inodeid); attr.set_nlink(nlink); - auto parentInodeWrapper = std::make_shared( - parentInode, metaClient_); + auto parentInodeWrapper = + std::make_shared(parentInode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(_, _)) - .WillOnce( - DoAll(SetArgReferee<1>(parentInodeWrapper), - Return(CURVEFS_ERROR::OK))) + .WillOnce(DoAll(SetArgReferee<1>(parentInodeWrapper), + Return(CURVEFS_ERROR::OK))) .WillOnce( DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgReferee<1>(parentInodeWrapper), - Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgReferee<1>(parentInodeWrapper), + Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*metaClient_, GetInodeAttr(_, _, _)) .WillOnce(DoAll(SetArgPointee<2>(attr), Return(MetaStatusCode::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .WillRepeatedly(Return(MetaStatusCode::OK)); - EXPECT_CALL(*inodeManager_, ShipToFlush(_)) - .Times(1); + EXPECT_CALL(*inodeManager_, ShipToFlush(_)).Times(1); CURVEFS_ERROR ret = client_->FuseOpUnlink(req, parent, name.c_str()); ASSERT_EQ(CURVEFS_ERROR::OK, ret); @@ -1794,8 +3019,8 @@ TEST_F(TestFuseS3Client, FuseOpOpen_Trunc_EnableSummary) { parentInode.mutable_xattr()->insert({XATTRENTRIES, "2"}); parentInode.mutable_xattr()->insert({XATTRFBYTES, "4196"}); - auto parentInodeWrapper = std::make_shared( - parentInode, metaClient_); + auto parentInodeWrapper = + std::make_shared(parentInode, metaClient_); uint64_t parentId = 1; @@ -1812,15 +3037,13 @@ TEST_F(TestFuseS3Client, FuseOpOpen_Trunc_EnableSummary) { EXPECT_CALL(*inodeManager_, GetInode(_, _)) .WillOnce( DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))) - .WillOnce( - DoAll(SetArgReferee<1>(parentInodeWrapper), - Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgReferee<1>(parentInodeWrapper), + Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*s3ClientAdaptor_, Truncate(_, _)) .WillOnce(Return(CURVEFS_ERROR::OK)); EXPECT_CALL(*metaClient_, UpdateInodeAttrWithOutNlink(_, _, _, _, _)) .WillRepeatedly(Return(MetaStatusCode::OK)); - EXPECT_CALL(*inodeManager_, ShipToFlush(_)) - .Times(0); + EXPECT_CALL(*inodeManager_, ShipToFlush(_)).Times(0); FileOut fileOut; CURVEFS_ERROR ret = client_->FuseOpOpen(req, ino, &fi, &fileOut); @@ -1853,27 +3076,22 @@ TEST_F(TestFuseS3Client, FuseOpListXattr) { // failed when get inode EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) .WillOnce( - DoAll(SetArgPointee<1>(inode), - Return(CURVEFS_ERROR::INTERNAL))); - CURVEFS_ERROR ret = client_->FuseOpListXattr( - req, ino, buf, size, &realSize); + DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::INTERNAL))); + CURVEFS_ERROR ret = + client_->FuseOpListXattr(req, ino, buf, size, &realSize); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); - ret = client_->FuseOpListXattr( - req, ino, buf, size, &realSize); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + ret = client_->FuseOpListXattr(req, ino, buf, size, &realSize); ASSERT_EQ(CURVEFS_ERROR::OK, ret); ASSERT_EQ(realSize, key.length() + 1); realSize = 0; inode.set_type(FsFileType::TYPE_DIRECTORY); EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); - ret = client_->FuseOpListXattr( - req, ino, buf, size, &realSize); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + ret = client_->FuseOpListXattr(req, ino, buf, size, &realSize); ASSERT_EQ(CURVEFS_ERROR::OK, ret); auto expected = key.length() + 1 + strlen(XATTRRFILES) + 1 + strlen(XATTRRSUBDIRS) + 1 + strlen(XATTRRENTRIES) + 1 + @@ -1882,18 +3100,14 @@ TEST_F(TestFuseS3Client, FuseOpListXattr) { realSize = 0; EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); - ret = client_->FuseOpListXattr( - req, ino, buf, expected - 1, &realSize); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + ret = client_->FuseOpListXattr(req, ino, buf, expected - 1, &realSize); ASSERT_EQ(CURVEFS_ERROR::OUT_OF_RANGE, ret); realSize = 0; EXPECT_CALL(*inodeManager_, GetInodeAttr(ino, _)) - .WillOnce( - DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); - ret = client_->FuseOpListXattr( - req, ino, buf, expected, &realSize); + .WillOnce(DoAll(SetArgPointee<1>(inode), Return(CURVEFS_ERROR::OK))); + ret = client_->FuseOpListXattr(req, ino, buf, expected, &realSize); ASSERT_EQ(CURVEFS_ERROR::OK, ret); } @@ -1906,8 +3120,7 @@ TEST_F(TestFuseS3Client, FuseOpSetXattr_TooLong) { char value[64 * 1024 + 1]; std::memset(value, 0, size); - CURVEFS_ERROR ret = client_->FuseOpSetXattr( - req, ino, name, value, size, 0); + CURVEFS_ERROR ret = client_->FuseOpSetXattr(req, ino, name, value, size, 0); ASSERT_EQ(CURVEFS_ERROR::OUT_OF_RANGE, ret); } @@ -1923,8 +3136,7 @@ TEST_F(TestFuseS3Client, FuseOpSetXattr) { // get inode failed EXPECT_CALL(*inodeManager_, GetInode(ino, _)) .WillOnce(Return(CURVEFS_ERROR::INTERNAL)); - CURVEFS_ERROR ret = client_->FuseOpSetXattr( - req, ino, name, value, size, 0); + CURVEFS_ERROR ret = client_->FuseOpSetXattr(req, ino, name, value, size, 0); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); // updateInode failed @@ -1934,8 +3146,7 @@ TEST_F(TestFuseS3Client, FuseOpSetXattr) { DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttrWithOutNlink(_, _, _, _, _)) .WillOnce(Return(MetaStatusCode::NOT_FOUND)); - ret = client_->FuseOpSetXattr( - req, ino, name, value, size, 0); + ret = client_->FuseOpSetXattr(req, ino, name, value, size, 0); ASSERT_EQ(CURVEFS_ERROR::NOTEXIST, ret); // success @@ -1944,8 +3155,7 @@ TEST_F(TestFuseS3Client, FuseOpSetXattr) { DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttrWithOutNlink(_, _, _, _, _)) .WillOnce(Return(MetaStatusCode::OK)); - ret = client_->FuseOpSetXattr( - req, ino, name, value, size, 0); + ret = client_->FuseOpSetXattr(req, ino, name, value, size, 0); ASSERT_EQ(CURVEFS_ERROR::OK, ret); } @@ -1955,7 +3165,7 @@ TEST_F(TestFuseS3Client, FuseOpWriteQosTest) { curvefs::client::common::FLAGS_fuseClientBurstWriteBytesSecs = 180; std::this_thread::sleep_for(std::chrono::milliseconds(1500)); - auto qosWriteTest = [&] (int id, int len) { + auto qosWriteTest = [&](int id, int len) { fuse_ino_t ino = id; Inode inode; inode.set_inodeid(ino); @@ -1963,8 +3173,8 @@ TEST_F(TestFuseS3Client, FuseOpWriteQosTest) { auto inodeWrapper = std::make_shared(inode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(ino, _)) - .WillOnce( - DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgReferee<1>(inodeWrapper), + Return(CURVEFS_ERROR::OK))); fuse_req_t req = nullptr; off_t off = 0; @@ -1980,8 +3190,8 @@ TEST_F(TestFuseS3Client, FuseOpWriteQosTest) { client_->Add(false, size); - CURVEFS_ERROR ret = client_->FuseOpWrite( - req, ino, buf.c_str(), size, off, &fi, &fileOut); + CURVEFS_ERROR ret = client_->FuseOpWrite(req, ino, buf.c_str(), size, + off, &fi, &fileOut); ASSERT_EQ(CURVEFS_ERROR::OK, ret); ASSERT_EQ(s3Size, fileOut.nwritten); }; @@ -1999,7 +3209,7 @@ TEST_F(TestFuseS3Client, FuseOpReadQosTest) { std::this_thread::sleep_for(std::chrono::milliseconds(1500)); - auto qosReadTest = [&] (int id, int size) { + auto qosReadTest = [&](int id, int size) { fuse_req_t req = nullptr; fuse_ino_t ino = id; off_t off = 0; @@ -2013,14 +3223,14 @@ TEST_F(TestFuseS3Client, FuseOpReadQosTest) { auto inodeWrapper = std::make_shared(inode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(ino, _)) - .WillOnce( - DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); + .WillOnce(DoAll(SetArgReferee<1>(inodeWrapper), + Return(CURVEFS_ERROR::OK))); std::unique_ptr buffer(new char[size]); size_t rSize = 0; client_->Add(true, size); - CURVEFS_ERROR ret = client_->FuseOpRead( - req, ino, size, off, &fi, buffer.get(), &rSize); + CURVEFS_ERROR ret = + client_->FuseOpRead(req, ino, size, off, &fi, buffer.get(), &rSize); ASSERT_EQ(CURVEFS_ERROR::OK, ret); ASSERT_EQ(0, rSize); };