diff --git a/curvefs/conf/tools.conf b/curvefs/conf/tools.conf index c88e7d7fd3..b34552f568 100644 --- a/curvefs/conf/tools.conf +++ b/curvefs/conf/tools.conf @@ -4,6 +4,8 @@ mdsDummyAddr=127.0.0.1:7700 # __CURVEADM_TEMPLATE__ ${cluster_mds_dummy_addr} _ # rpc timeout rpcTimeoutMs=10000 rpcRetryTimes=5 +# rpc stream idle timeout +rpcStreamIdleTimeoutMs=10000 # topo file path topoFilePath=curvefs/test/tools/topo_example.json # __CURVEADM_TEMPLATE__ /curvefs/tools/conf/topology.json __CURVEADM_TEMPLATE__ __ANSIBLE_TEMPLATE__ {{ project_root_dest }}/conf/topology.json __ANSIBLE_TEMPLATE__ # metaserver external address diff --git a/curvefs/proto/topology.proto b/curvefs/proto/topology.proto index 310c1fc36b..2dbeffc8a1 100644 --- a/curvefs/proto/topology.proto +++ b/curvefs/proto/topology.proto @@ -381,18 +381,6 @@ message CommitTxResponse { required TopoStatusCode statusCode = 1; } -message ListPartitionsRequest { - repeated uint32 fsId = 1; -} - -message PartitionInfoList { - repeated common.PartitionInfo partitionInfoList = 1; -} - -message ListPartitionsResponse { - required TopoStatusCode statusCode = 1; - map fsId2partitionList = 2; -} message CopysetKey { required uint32 poolId = 1; @@ -485,7 +473,6 @@ service TopologyService { rpc GetCopysetOfPartition(GetCopysetOfPartitionRequest) returns (GetCopysetOfPartitionResponse); rpc CommitTx(CommitTxRequest) returns (CommitTxResponse); rpc GetCopysetsInfo (GetCopysetsInfoRequest) returns (GetCopysetsInfoResponse); - rpc ListPartitions(ListPartitionsRequest) returns (ListPartitionsResponse); rpc ListCopysetInfo(ListCopysetInfoRequest) returns (ListCopysetInfoResponse); rpc StatMetadataUsage(StatMetadataUsageRequest) returns (StatMetadataUsageResponse); diff --git a/curvefs/src/tools/BUILD b/curvefs/src/tools/BUILD index a5cb698514..9d18794b6a 100644 --- a/curvefs/src/tools/BUILD +++ b/curvefs/src/tools/BUILD @@ -66,11 +66,13 @@ cc_library( "//curvefs/proto:space_cc_proto", "//curvefs/src/mds/common:fs_mds_common", "//curvefs/src/mds/topology:curvefs_deal_peerid", + "//curvefs/src/common:curvefs_common", "//external:brpc", "//external:gflags", "//external:glog", "//external:json", "//src/common:curve_common", "//src/mds/topology", + "@com_google_absl//absl/cleanup", ], ) diff --git a/curvefs/src/tools/curvefs_tool.h b/curvefs/src/tools/curvefs_tool.h index 4616c8da58..4e0adbed10 100644 --- a/curvefs/src/tools/curvefs_tool.h +++ b/curvefs/src/tools/curvefs_tool.h @@ -38,6 +38,8 @@ #include #include +#include "absl/cleanup/cleanup.h" +#include "curvefs/src/common/rpc_stream.h" #include "curvefs/src/tools/curvefs_tool_define.h" #include "curvefs/src/tools/curvefs_tool_metric.h" #include "src/common/configuration.h" @@ -45,10 +47,16 @@ DECLARE_string(confPath); DECLARE_uint32(rpcTimeoutMs); DECLARE_uint32(rpcRetryTimes); +DECLARE_uint32(rpcStreamIdleTimeoutMs); namespace curvefs { namespace tools { +using ::curvefs::common::StreamClient; +using ::curvefs::common::StreamConnection; +using ::curvefs::common::StreamOptions; +using ::curvefs::common::StreamStatus; + class CurvefsTool { public: CurvefsTool() {} @@ -120,13 +128,15 @@ class CurvefsToolRpc : public CurvefsTool { const std::shared_ptr& response, const std::shared_ptr& service_stub, const std::function& - service_stub_func) { + service_stub_func, + const std::shared_ptr& streamClient) { channel_ = channel; controller_ = controller; requestQueue_ = requestQueue; response_ = response; service_stub_ = service_stub; service_stub_func_ = service_stub_func; + streamClient_ = streamClient; InitHostsAddr(); return 0; } @@ -136,6 +146,7 @@ class CurvefsToolRpc : public CurvefsTool { controller_ = std::make_shared(); response_ = std::make_shared(); service_stub_ = std::make_shared(channel_.get()); + streamClient_ = std::make_shared(); // add need update FlagInfos AddUpdateFlags(); @@ -196,11 +207,27 @@ class CurvefsToolRpc : public CurvefsTool { * as long as one succeeds, it returns true and ends sending */ virtual bool SendRequestToServices() { - uint32_t failHostNumner = 0; + uint32_t failHostNumber = 0; + bool ret = false; for (const std::string& host : hostsAddr_) { SetController(); - if (channel_->Init(host.c_str(), nullptr) != 0) { - std::cerr << "fail init channel to host: " << host << std::endl; + brpc::ChannelOptions channelOpt; + if (isStreaming_) { + // set stream rpc client + channelOpt.connection_group = "streaming"; + StreamOptions streamOpt(FLAGS_rpcStreamIdleTimeoutMs); + connection_ = streamClient_->Connect( + controller_.get(), receiveCallback_, streamOpt); + if (nullptr == connection_ || nullptr == receiveCallback_) { + errorOutput_ << "Stream connect " << host << " failed\n"; + ++failHostNumber; + continue; + } + } + if (channel_->Init(host.c_str(), &channelOpt) != 0) { + errorOutput_ << "fail init channel to host: " << host + << std::endl; + ++failHostNumber; continue; } // if service_stub_func_ does not assign a value @@ -208,20 +235,32 @@ class CurvefsToolRpc : public CurvefsTool { service_stub_func_(controller_.get(), &requestQueue_.front(), response_.get()); if (controller_->Failed()) { - ++failHostNumner; + ++failHostNumber; + } + if (isStreaming_) { + auto status = connection_->WaitAllDataReceived(); + if (status != StreamStatus::STREAM_OK) { + errorOutput_ << "Receive stream data from " << host + << " failed , status=" << status << std::endl; + } } if (AfterSendRequestToHost(host) == true) { controller_->Reset(); - return true; + ret = true; + break; } controller_->Reset(); + if (isStreaming_ && connection_ != nullptr) { + streamClient_->Close(connection_); + connection_ = nullptr; + } SetController(); } - if (hostsAddr_.size() != failHostNumner) { + if (hostsAddr_.size() != failHostNumber) { errorOutput_.str(""); } - // send request to all host failed - return false; + + return ret; } virtual void SetController() { @@ -288,6 +327,10 @@ class CurvefsToolRpc : public CurvefsTool { } } + void SetStreamingRpc(bool isStreaming) { + isStreaming_ = isStreaming; + } + protected: /** * @brief save the host who will be sended request @@ -317,7 +360,8 @@ class CurvefsToolRpc : public CurvefsTool { * it is core function of this class * make sure uint test cover SendRequestToServices */ - std::function service_stub_func_; + std::function + service_stub_func_ = nullptr; /** * @brief save the functor which defined in curvefs_tool_define.h * @@ -326,6 +370,21 @@ class CurvefsToolRpc : public CurvefsTool { std::vector> updateFlagsFunc_; + /** + * @brief whether to use stream rpc api + */ + bool isStreaming_ = false; + /** + * @brief rpc streaming client for too large data + */ + std::shared_ptr streamClient_; + /** + * @brief rpc stream client callback function for processing received data + * + */ + std::function receiveCallback_ = nullptr; + + std::shared_ptr connection_; }; class CurvefsToolMetric : public CurvefsTool { diff --git a/curvefs/src/tools/curvefs_tool_define.cpp b/curvefs/src/tools/curvefs_tool_define.cpp index ab53404a11..a333b0cae0 100644 --- a/curvefs/src/tools/curvefs_tool_define.cpp +++ b/curvefs/src/tools/curvefs_tool_define.cpp @@ -60,6 +60,7 @@ DEFINE_bool(enableSumInDir, false, "statistic info in xattr"); DEFINE_uint64(capacity, (uint64_t)100 * 1024 * 1024 * 1024, "capacity of fs, default 100G"); DEFINE_string(user, "anonymous", "user of request"); +DEFINE_string(inodeId, "1,2,3", "inodes id"); // list-topology DEFINE_string(jsonPath, "/tmp/topology.json", "output json path"); @@ -78,6 +79,8 @@ DEFINE_string(volumeBitmapLocation, "AtStart", "volume space bitmap location, support |AtStart| and |AtEnd|"); +DEFINE_uint32(rpcStreamIdleTimeoutMs, 10000, "rpc stream idle timeout"); + namespace curvefs { namespace tools { @@ -218,10 +221,14 @@ std::function &FLAGS_s3_chunksize); std::function - SetEnableSumInDir = - std::bind(&SetFlagInfo, std::placeholders::_1, - std::placeholders::_2, "enableSumInDir", - &FLAGS_enableSumInDir); + SetEnableSumInDir = std::bind(&SetFlagInfo, std::placeholders::_1, + std::placeholders::_2, "enableSumInDir", + &FLAGS_enableSumInDir); + +std::function + SetRpcStreamIdleTimeoutMs = std::bind( + &SetFlagInfo, std::placeholders::_1, std::placeholders::_2, + "rpcStreamIdleTimeoutMs", &FLAGS_rpcStreamIdleTimeoutMs); /* check flag */ std::function CheckMetaserverIdDefault = @@ -255,6 +262,10 @@ std::function CheckJsonPathDefault = std::bind(&CheckFlagInfoDefault, std::placeholders::_1, "jsonPath"); +std::function CheckInodeIdDefault = + std::bind(&CheckFlagInfoDefault, std::placeholders::_1, + "inodeId"); + /* translate to string */ auto StrVec2Str(const std::vector& strVec) -> std::string { diff --git a/curvefs/src/tools/curvefs_tool_define.h b/curvefs/src/tools/curvefs_tool_define.h index f6f70967c5..5b1cd4f16e 100644 --- a/curvefs/src/tools/curvefs_tool_define.h +++ b/curvefs/src/tools/curvefs_tool_define.h @@ -74,12 +74,16 @@ const char kPartitionQueryCmd[] = "query-partition"; const char kMetaserverQueryCmd[] = "query-metaserver"; // fs-query const char kFsQueryCmd[] = "query-fs"; +// Inode-query +const char kInodeQueryCmd[] = "query-inode"; // fsinfo-list const char kFsInfoListCmd[] = "list-fs"; // list-fs-copysetid const char kCopysetInfoListCmd[] = "list-copysetInfo"; // list-topology const char kTopologyListCmd[] = "list-topology"; +// list-partition +const char kPartitionListCmd[] = "list-partition"; // no-invoke Used for commands that are not directly invoked const char kNoInvokeCmd[] = "no-invoke"; @@ -99,6 +103,7 @@ const char kHelpStr[] = "list-fs: list all fs in cluster\n" "list-copysetInfo: list all copysetInfo in cluster\n" "list-topology: list cluster's topology\n" + "list-topology: list partition by fsId\n" "create-topology: create cluster topology based on topo.json\n" "create-fs: create fs\n" "umount-fs: umount curvefs from local and cluster\n" @@ -109,6 +114,7 @@ const char kHelpStr[] = "query-partition: query copyset in partition by partitionId\n" "query-metaserver: query metaserver by metaserverId or metaserverName\n" "query-fs: query fs by fsId or fsName\n" + "query-inode: query inode\n" "You can specify the config path by -confPath to avoid typing too many " "options\n"; // NOLINT @@ -260,6 +266,9 @@ extern std::function SetEnableSumInDir; +extern std::function + SetRpcStreamIdleTimeoutMs; /* checkout the flag is default */ extern std::function @@ -281,6 +290,8 @@ extern std::function extern std::function CheckJsonPathDefault; +extern std::function CheckInodeIdDefault; + /* translate to string */ std::string StrVec2Str(const std::vector&); diff --git a/curvefs/src/tools/curvefs_tool_factory.cpp b/curvefs/src/tools/curvefs_tool_factory.cpp index 50fc3e73a6..41cee17986 100644 --- a/curvefs/src/tools/curvefs_tool_factory.cpp +++ b/curvefs/src/tools/curvefs_tool_factory.cpp @@ -33,6 +33,7 @@ #include "curvefs/src/tools/list/curvefs_topology_list.h" #include "curvefs/src/tools/query/curvefs_copyset_query.h" #include "curvefs/src/tools/query/curvefs_fs_query.h" +#include "curvefs/src/tools/query/curvefs_inode_query.h" #include "curvefs/src/tools/query/curvefs_metaserver_query.h" #include "curvefs/src/tools/query/curvefs_partition_query.h" #include "curvefs/src/tools/status/curvefs_copyset_status.h" @@ -43,6 +44,7 @@ #include "curvefs/src/tools/umount/curvefs_umount_fs_tool.h" #include "curvefs/src/tools/usage/curvefs_metadata_usage_tool.h" #include "curvefs/src/tools/version/curvefs_version_tool.h" +#include "curvefs/src/tools/list/curvefs_partition_list.h" namespace curvefs { namespace tools { @@ -99,6 +101,10 @@ CurvefsToolFactory::CurvefsToolFactory() { RegisterCurvefsTool(std::string(kTopologyListCmd), CurvefsToolCreator::Create); + // list-partition + RegisterCurvefsTool(std::string(kPartitionListCmd), + CurvefsToolCreator::Create); + // query-copyset RegisterCurvefsTool(std::string(kCopysetQueryCmd), CurvefsToolCreator::Create); @@ -115,6 +121,10 @@ CurvefsToolFactory::CurvefsToolFactory() { RegisterCurvefsTool(std::string(kFsQueryCmd), CurvefsToolCreator::Create); + // query-inode + RegisterCurvefsTool(std::string(kInodeQueryCmd), + CurvefsToolCreator::Create); + // delete-fs RegisterCurvefsTool(std::string(kDeleteFsCmd), CurvefsToolCreator::Create); diff --git a/curvefs/src/tools/list/curvefs_partition_list.cpp b/curvefs/src/tools/list/curvefs_partition_list.cpp new file mode 100644 index 0000000000..fdc1ed90a3 --- /dev/null +++ b/curvefs/src/tools/list/curvefs_partition_list.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022 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: 2022-04-29 + * Author: chengyi01 + */ + +#include "curvefs/src/tools/list/curvefs_partition_list.h" + +#include + +#include +#include +#include +#include +#include + +#include "curvefs/src/tools/curvefs_tool_define.h" +#include "src/common/string_util.h" + +DECLARE_string(mdsAddr); +DECLARE_string(fsId); + +namespace curvefs { +namespace tools { +namespace list { + +void PartitionListTool::PrintHelp() { + CurvefsToolRpc::PrintHelp(); + std::cout << " -fsId=" << FLAGS_fsId << " [-mdsAddr=" << FLAGS_mdsAddr + << "]" << std::endl; +} + +void PartitionListTool::AddUpdateFlags() { + AddUpdateFlagsFunc(curvefs::tools::SetMdsAddr); +} + +int PartitionListTool::Init() { + if (CurvefsToolRpc::Init() != 0) { + return -1; + } + + curve::common::SplitString(FLAGS_mdsAddr, ",", &hostsAddr_); + google::CommandLineFlagInfo info; + if (CheckFsIdDefault(&info)) { + std::cerr << "no -fsId=*, please use --example check!" << std::endl; + return -1; + } + + std::vector fsIds; + curve::common::SplitString(FLAGS_fsId, ",", &fsIds); + + service_stub_func_ = + std::bind(&curvefs::mds::topology::TopologyService_Stub::ListPartition, + service_stub_.get(), std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, nullptr); + + curvefs::mds::topology::ListPartitionRequest request; + for (const auto& i : fsIds) { + uint32_t fsId; + curve::common::StringToUl(i, &fsId); + request.set_fsid(fsId); + AddRequest(request); + } + + return 0; +} + +bool PartitionListTool::AfterSendRequestToHost(const std::string& host) { + bool ret = false; + if (controller_->Failed()) { + errorOutput_ << "get fsinfo from mds: " << host + << " failed, errorcode= " << controller_->ErrorCode() + << ", error text " << controller_->ErrorText() << "\n"; + } else { + if (response_->statuscode() != mds::topology::TopoStatusCode::TOPO_OK) { + std::cerr << "list partitions failed, errorcode= " + << mds::topology::TopoStatusCode_Name( + response_->statuscode()) + << std::endl; + } else { + fsId2PartitionList_[requestQueue_.front().fsid()] = + response_->partitioninfolist(); + if (show_) { + std::cout << response_->DebugString() << std::endl; + ret = true; + } + } + } + return ret; +} + +} // namespace list +} // namespace tools +} // namespace curvefs diff --git a/curvefs/src/tools/list/curvefs_partition_list.h b/curvefs/src/tools/list/curvefs_partition_list.h new file mode 100644 index 0000000000..641808319b --- /dev/null +++ b/curvefs/src/tools/list/curvefs_partition_list.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 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: 2022-04-28 + * Author: chengyi01 + */ + +#ifndef CURVEFS_SRC_TOOLS_LIST_CURVEFS_PARTITION_LIST_H_ +#define CURVEFS_SRC_TOOLS_LIST_CURVEFS_PARTITION_LIST_H_ + +#include +#include + +#include +#include + +#include "curvefs/proto/topology.pb.h" +#include "curvefs/proto/common.pb.h" +#include "curvefs/src/tools/curvefs_tool.h" +#include "curvefs/src/tools/curvefs_tool_define.h" + +namespace curvefs { +namespace tools { +namespace list { + +using PartitionInfoList = + google::protobuf::RepeatedPtrField; + +class PartitionListTool + : public CurvefsToolRpc { + public: + explicit PartitionListTool(const std::string& cmd = kPartitionListCmd, + bool show = true) + : CurvefsToolRpc(cmd) { + show_ = show; + } + void PrintHelp() override; + int Init() override; + + std::unordered_map + GetFsId2PartitionInfoList() { + return fsId2PartitionList_; + } + + protected: + void AddUpdateFlags() override; + bool AfterSendRequestToHost(const std::string& host) override; + + protected: + std::unordered_map fsId2PartitionList_; +}; +} // namespace list +} // namespace tools +} // namespace curvefs + +#endif // CURVEFS_SRC_TOOLS_LIST_CURVEFS_PARTITION_LIST_H_ diff --git a/curvefs/src/tools/query/curvefs_inode.cpp b/curvefs/src/tools/query/curvefs_inode.cpp new file mode 100644 index 0000000000..bd0bc95a77 --- /dev/null +++ b/curvefs/src/tools/query/curvefs_inode.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2022 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: 2022-04-29 + * Author: chengyi01 + */ + +#include "curvefs/src/tools/query/curvefs_inode.h" + +#include +#include +#include + +DECLARE_string(metaserverAddr); +DECLARE_string(poolId); +DECLARE_string(copysetId); +DECLARE_string(partitionId); +DECLARE_string(fsId); +DECLARE_string(inodeId); + +#include "src/common/string_util.h" + +namespace curvefs { +namespace tools { +namespace query { + +void InodeTool::PrintHelp() { + CurvefsToolRpc::PrintHelp(); + std::cout << " -poolId=" << FLAGS_poolId + << " -copysetId=" << FLAGS_copysetId + << " -partitionId=" << FLAGS_partitionId + << " -fsId=" << FLAGS_fsId << " -inodeId=" << FLAGS_inodeId + << " [-metaserverAddr=" << FLAGS_metaserverAddr + << " -rpcStreamIdleTimeoutMs=" << FLAGS_rpcStreamIdleTimeoutMs + << "]"; + std::cout << std::endl; +} + +int InodeTool::Init() { + if (CurvefsToolRpc::Init() != 0) { + return -1; + } + + curve::common::SplitString(FLAGS_metaserverAddr, ",", &hostsAddr_); + + std::vector poolsId; + curve::common::SplitString(FLAGS_poolId, ",", &poolsId); + + std::vector copysetsId; + curve::common::SplitString(FLAGS_copysetId, ",", ©setsId); + + std::vector partitionId; + curve::common::SplitString(FLAGS_partitionId, ",", &partitionId); + + std::vector fsId; + curve::common::SplitString(FLAGS_fsId, ",", &fsId); + + std::vector inodeId; + curve::common::SplitString(FLAGS_inodeId, ",", &inodeId); + + if (poolsId.size() != copysetsId.size() || + poolsId.size() != partitionId.size() || poolsId.size() != fsId.size() || + poolsId.size() != inodeId.size()) { + std::cout << "fsId:" << FLAGS_fsId << " poolId:" << FLAGS_poolId + << " copysetId:" << FLAGS_copysetId + << " partitionId:" << FLAGS_partitionId + << " inodeId:" << FLAGS_inodeId << " must be the same size" + << std::endl; + return -1; + } + + for (size_t i = 0; i < poolsId.size(); ++i) { + curvefs::metaserver::GetInodeRequest request; + request.set_poolid(std::stoi(poolsId[i])); + request.set_copysetid(std::stoi(copysetsId[i])); + request.set_partitionid(std::stoi(partitionId[i])); + request.set_fsid(std::stoi(fsId[i])); + request.set_inodeid(std::stoi(inodeId[i])); + SetStreamingRpc(false); + request.set_supportstreaming(true); + AddRequest(request); + } + + service_stub_func_ = + std::bind(&curvefs::metaserver::MetaServerService_Stub::GetInode, + service_stub_.get(), std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, nullptr); + + return 0; +} + +void InodeTool::AddUpdateFlags() { + AddUpdateFlagsFunc(curvefs::tools::SetMetaserverAddr); + AddUpdateFlagsFunc(curvefs::tools::SetRpcStreamIdleTimeoutMs); +} + +bool InodeTool::AfterSendRequestToHost(const std::string& host) { + bool ret = false; + if (controller_->Failed()) { + errorOutput_ << "send request " + << " to metaserver: " << host + << " failed, errorcode= " << controller_->ErrorCode() + << ", error text " << controller_->ErrorText() << "\n"; + } else { + if (response_->statuscode() == metaserver::MetaStatusCode::OK) { + ret = UpdateInode2InodeBaseInfoList_(requestQueue_.front(), + response_->inode()); + if (show_) { + std::cout << "inode:\n" << requestQueue_.front().DebugString() + << response_->inode().DebugString(); + } + } else { + errorOutput_ << "request: " + << requestQueue_.front().ShortDebugString() + << " get response: " << response_->ShortDebugString() + << std::endl; + } + } + return ret; +} + +bool InodeTool::CheckRequiredFlagDefault() { + google::CommandLineFlagInfo info; + if (CheckPoolIdDefault(&info) && CheckCopysetIdDefault(&info) && + CheckPartitionIdDefault(&info) && CheckFsIdDefault(&info) && + CheckInodeIdDefault(&info)) { + std::cerr << "no -poolId=*,* -copysetId=*,* -partitionId=*,* -fsId=*,* " + "-inodeId=*,*" + << std::endl; + return true; + } + return false; +} + +bool InodeTool::UpdateInode2InodeBaseInfoList_(const InodeBase& inode, + const InodeBaseInfo& list) { + bool ret = true; + auto iter = std::find_if( + inode2InodeBaseInfoList_.begin(), inode2InodeBaseInfoList_.end(), + [inode](const std::pair>& a) { + return a.first.fsid() == inode.fsid() && + a.first.inodeid() == inode.inodeid(); + }); + if (iter == inode2InodeBaseInfoList_.end()) { + inode2InodeBaseInfoList_.insert( + {inode, std::vector{list}}); + } else { + iter->second.emplace_back(list); + ret = false; + } + return ret; +} + +} // namespace query +} // namespace tools +} // namespace curvefs diff --git a/curvefs/src/tools/query/curvefs_inode.h b/curvefs/src/tools/query/curvefs_inode.h new file mode 100644 index 0000000000..15b1e47822 --- /dev/null +++ b/curvefs/src/tools/query/curvefs_inode.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 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: 2022-04-29 + * Author: chengyi01 + */ +#ifndef CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_H_ +#define CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_H_ + +#include +#include + +#include +#include +#include + +#include "curvefs/proto/metaserver.pb.h" +#include "curvefs/src/tools/curvefs_tool.h" +#include "curvefs/src/tools/curvefs_tool_define.h" +#include "curvefs/src/tools/query/curvefs_inode_s3infomap.h" + +namespace curvefs { +namespace tools { +namespace query { + +using InodeBaseInfo = metaserver::Inode; + +class InodeTool + : public CurvefsToolRpc { + public: + explicit InodeTool(const std::string& cmd = kNoInvokeCmd, bool show = true) + : CurvefsToolRpc(cmd) { + show_ = show; + } + + void PrintHelp() override; + int Init() override; + std::unordered_map, HashInodeBase, + KeyEuqalInodeBase> + GetInode2InodeBaseInfoList() { + return inode2InodeBaseInfoList_; + } + + protected: + void AddUpdateFlags() override; + bool AfterSendRequestToHost(const std::string& host) override; + bool CheckRequiredFlagDefault() override; + + /** + * @brief + * + * @param inode + * @param list + * @return true : success + * @return false : inode2InodeBaseInfoList_[inode].second.size() > 0 + * means found two inode in the fs + */ + bool UpdateInode2InodeBaseInfoList_(const InodeBase& inode, + const InodeBaseInfo& list); + + protected: + std::unordered_map, HashInodeBase, + KeyEuqalInodeBase> + inode2InodeBaseInfoList_; +}; + +} // namespace query +} // namespace tools +} // namespace curvefs + +#endif // CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_H_ diff --git a/curvefs/src/tools/query/curvefs_inode_query.cpp b/curvefs/src/tools/query/curvefs_inode_query.cpp new file mode 100644 index 0000000000..cfcad11717 --- /dev/null +++ b/curvefs/src/tools/query/curvefs_inode_query.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2022 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: 2022-03-25 + * Author: chengyi01 + */ + +#include "curvefs/src/tools/query/curvefs_inode_query.h" + +#include +#include +#include +#include +#include +#include + +#include "src/common/string_util.h" + +DECLARE_string(mdsAddr); +DECLARE_string(metaserverAddr); +DECLARE_string(poolId); +DECLARE_string(copysetId); +DECLARE_string(partitionId); +DECLARE_string(fsId); +DECLARE_string(inodeId); +DECLARE_uint32(rpcStreamIdleTimeoutMs); + +namespace curvefs { +namespace tools { +namespace query { + +void InodeQueryTool::PrintHelp() { + CurvefsTool::PrintHelp(); + std::cout << " -fsId=" << FLAGS_fsId << " -inodeId=" << FLAGS_inodeId + << " [-mds=" << FLAGS_mdsAddr + << " -metaserverAddr=" << FLAGS_metaserverAddr + << " -rpcStreamIdleTimeoutMs=" << FLAGS_rpcStreamIdleTimeoutMs + << "]"; + std::cout << std::endl; +} + +int InodeQueryTool::Init() { + std::vector fsIds; + curve::common::SplitString(FLAGS_fsId, ",", &fsIds); + std::vector inodeIds; + curve::common::SplitString(FLAGS_inodeId, ",", &inodeIds); + if (fsIds.size() != inodeIds.size()) { + std::cout << "fsId and inodeId must be the same size" << std::endl; + return -1; + } + for (size_t i = 0; i < fsIds.size(); ++i) { + InodeBase tmp; + uint64_t tmpFsId; + curve::common::StringToUll(fsIds[i], &tmpFsId); + tmp.set_fsid(tmpFsId); + + uint64_t tmpInodeId; + curve::common::StringToUll(inodeIds[i], &tmpInodeId); + tmp.set_inodeid(tmpInodeId); + + inodeBases_.emplace_back(tmp); + } + return 0; +} + +int InodeQueryTool::RunCommand() { + // get fs partition list + int ret = partitionListTool_.Run(); + fsId2PartitionList_ = partitionListTool_.GetFsId2PartitionInfoList(); + + // clear and reset flag + FLAGS_fsId = FLAGS_poolId = FLAGS_copysetId = FLAGS_partitionId = + FLAGS_inodeId = ""; + for (auto& inode : inodeBases_) { + if (GetInodeInfo(&inode)) { + FLAGS_fsId.append(std::to_string(inode.fsid()) + ","); + FLAGS_poolId.append(std::to_string(inode.poolid()) + ","); + FLAGS_copysetId.append(std::to_string(inode.copysetid()) + ","); + FLAGS_partitionId.append(std::to_string(inode.partitionid()) + ","); + FLAGS_inodeId.append(std::to_string(inode.inodeid()) + ","); + } + } + + // get InodeBaseInfo + if (inodeTool_.Run() != 0) { + ret = -1; + } + inode2InodeBaseInfoList_ = inodeTool_.GetInode2InodeBaseInfoList(); + + // get s3chunkinfo + if (inodeS3InfoMapTool_.Run() != 0) { + ret = -1; + } + inode2S3ChunkInfoList_ = inodeS3InfoMapTool_.GetInode2S3ChunkInfoList(); + + // print + for (auto const& i : inodeBases_) { + std::cout << "fsId: " << i.fsid() + << " inodeId: " << i.inodeid() << std::endl; + // base info + auto iter1 = inode2InodeBaseInfoList_.find(i); + if (iter1 != inode2InodeBaseInfoList_.end()) { + if (iter1->second.empty()) { + std::cerr << "inode base info is empty" << std::endl; + ret = -1; + } + for (auto const& base : iter1->second) { + std::cout << "-baseInfo:\n" << base.DebugString(); + } + } else { + std::cerr << "inode baseinfo not found" << std::endl; + ret = -1; + } + + // s3 chunk info map + auto iter2 = inode2S3ChunkInfoList_.find(i); + if (iter2 != inode2S3ChunkInfoList_.end()) { + if (iter2->second.s3chunks().empty()) { + std::cout << "no s3chunkinfo" << std::endl; + } + for (auto const& s3Chunkinfo : iter2->second.s3chunks()) { + std::cout << "-----------------\n-s3ChunkInfo:\n" + << s3Chunkinfo.DebugString() << std::endl; + } + std::cout << "Total s3chunkinfo: " + << iter2->second.s3chunks().size() << std::endl; + } else { + std::cerr << "inode s3ChunkinfoMap not found" << std::endl; + ret = -1; + } + + std::cout << std::endl; + } + + return ret; +} + +bool InodeQueryTool::GetInodeInfo(InodeBase* inode) { + // find fs partitionlist + auto fs2ParListIter = fsId2PartitionList_.find(inode->fsid()); + if (fs2ParListIter == fsId2PartitionList_.end()) { + errorOutput_ << "fsId: " << inode->fsid() << " no partition!"; + return false; + } + + // find partition which inode belongs to + auto partitionIter = std::find_if( + fs2ParListIter->second.begin(), fs2ParListIter->second.end(), + [=](const common::PartitionInfo& a) -> bool { + return a.fsid() == inode->fsid() && a.start() <= inode->inodeid() && + a.end() >= inode->inodeid(); + }); + if (partitionIter == fs2ParListIter->second.end()) { + errorOutput_ << "fsId: " << inode->fsid() + << " inodeId: " << inode->inodeid() + << " not found in any partition!"; + return false; + } + + // set inode + inode->set_poolid(partitionIter->poolid()); + inode->set_partitionid(partitionIter->partitionid()); + inode->set_copysetid(partitionIter->copysetid()); + return true; +} + +} // namespace query +} // namespace tools +} // namespace curvefs diff --git a/curvefs/src/tools/query/curvefs_inode_query.h b/curvefs/src/tools/query/curvefs_inode_query.h new file mode 100644 index 0000000000..688896efc4 --- /dev/null +++ b/curvefs/src/tools/query/curvefs_inode_query.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022 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: 2022-03-25 + * Author: chengyi01 + */ + +#ifndef CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_QUERY_H_ +#define CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_QUERY_H_ + +#include +#include + +#include +#include +#include +#include +#include + +#include "curvefs/src/tools/curvefs_tool.h" +#include "curvefs/src/tools/curvefs_tool_define.h" +#include "curvefs/src/tools/list/curvefs_partition_list.h" +#include "curvefs/src/tools/query/curvefs_inode_s3infomap.h" +#include "curvefs/src/tools/query/curvefs_inode.h" + +namespace curvefs { +namespace tools { +namespace query { + +using InodeBase = curvefs::metaserver::GetInodeRequest; + +using PartitionInfoList = + google::protobuf::RepeatedPtrField; + +class InodeQueryTool : public CurvefsTool { + public: + explicit InodeQueryTool(const std::string& cmd = kInodeQueryCmd, + bool show = true) + : CurvefsTool(cmd), + partitionListTool_(kNoInvokeCmd, false), + inodeS3InfoMapTool_(kNoInvokeCmd, false), + inodeTool_(kNoInvokeCmd, false) { + show_ = show; + } + void PrintHelp() override; + int Init() override; + int RunCommand() override; + + protected: + /** + * @brief Find in fsId2PartitionList_ with fsid and inodeid and populate + * remaining fields + * + * @param inode + * @return true + found + * @return false not found + */ + bool GetInodeInfo(InodeBase* inode); + + std::vector inodeBases_; + list::PartitionListTool partitionListTool_; + InodeS3InfoMapTool inodeS3InfoMapTool_; + InodeTool inodeTool_; + std::unordered_map fsId2PartitionList_; + std::unordered_map + inode2S3ChunkInfoList_; + std::unordered_map, HashInodeBase, + KeyEuqalInodeBase> + inode2InodeBaseInfoList_; +}; + +} // namespace query +} // namespace tools +} // namespace curvefs + +#endif // CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_QUERY_H_ diff --git a/curvefs/src/tools/query/curvefs_inode_s3infomap.cpp b/curvefs/src/tools/query/curvefs_inode_s3infomap.cpp new file mode 100644 index 0000000000..de0881318f --- /dev/null +++ b/curvefs/src/tools/query/curvefs_inode_s3infomap.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2022 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: 2022-03-25 + * Author: chengyi01 + */ + +#include "curvefs/src/tools/query/curvefs_inode_s3infomap.h" + +#include +#include +#include + +#include "src/common/string_util.h" + +DECLARE_string(metaserverAddr); +DECLARE_string(poolId); +DECLARE_string(copysetId); +DECLARE_string(partitionId); +DECLARE_string(fsId); +DECLARE_string(inodeId); +DECLARE_uint32(rpcStreamIdleTimeoutMs); + +namespace curvefs { +namespace tools { +namespace query { + +InodeBase TraslateInodeBase( + const curvefs::metaserver::GetOrModifyS3ChunkInfoRequest& source) { + InodeBase target; + target.set_poolid(source.poolid()); + target.set_copysetid(source.copysetid()); + target.set_partitionid(source.partitionid()); + target.set_fsid(source.fsid()); + target.set_inodeid(source.inodeid()); + return target; +} + +void InodeS3InfoMapTool::PrintHelp() { + CurvefsToolRpc::PrintHelp(); + std::cout << " -poolId=" << FLAGS_poolId + << " -copysetId=" << FLAGS_copysetId + << " -partitionId=" << FLAGS_partitionId + << " -fsId=" << FLAGS_fsId << " -inodeId=" << FLAGS_inodeId + << " [-metaserverAddr=" << FLAGS_metaserverAddr + << " -rpcStreamIdleTimeoutMs=" << FLAGS_rpcStreamIdleTimeoutMs + << "]"; + std::cout << std::endl; +} + +void InodeS3InfoMapTool::AddUpdateFlags() { + AddUpdateFlagsFunc(curvefs::tools::SetMetaserverAddr); + AddUpdateFlagsFunc(curvefs::tools::SetRpcStreamIdleTimeoutMs); +} + +int InodeS3InfoMapTool::Init() { + if (CurvefsToolRpc::Init() != 0) { + return -1; + } + + curve::common::SplitString(FLAGS_metaserverAddr, ",", &hostsAddr_); + + std::vector poolsId; + curve::common::SplitString(FLAGS_poolId, ",", &poolsId); + + std::vector copysetsId; + curve::common::SplitString(FLAGS_copysetId, ",", ©setsId); + + std::vector partitionId; + curve::common::SplitString(FLAGS_partitionId, ",", &partitionId); + + std::vector fsId; + curve::common::SplitString(FLAGS_fsId, ",", &fsId); + + std::vector inodeId; + curve::common::SplitString(FLAGS_inodeId, ",", &inodeId); + + if (poolsId.size() != copysetsId.size() || + poolsId.size() != partitionId.size() || poolsId.size() != fsId.size() || + poolsId.size() != inodeId.size()) { + std::cout << "fsId:" << FLAGS_fsId << " poolId:" << FLAGS_poolId + << " copysetId:" << FLAGS_copysetId + << " partitionId:" << FLAGS_partitionId + << " inodeId:" << FLAGS_inodeId << " must be the same size" + << std::endl; + return -1; + } + + for (size_t i = 0; i < poolsId.size(); ++i) { + curvefs::metaserver::GetOrModifyS3ChunkInfoRequest request; + request.set_poolid(std::stoi(poolsId[i])); + request.set_copysetid(std::stoi(copysetsId[i])); + request.set_partitionid(std::stoi(partitionId[i])); + request.set_fsid(std::stoi(fsId[i])); + request.set_inodeid(std::stoi(inodeId[i])); + request.set_returns3chunkinfomap(true); + SetStreamingRpc(true); + request.set_supportstreaming(isStreaming_); + AddRequest(request); + } + + service_stub_func_ = std::bind( + &curvefs::metaserver::MetaServerService_Stub::GetOrModifyS3ChunkInfo, + service_stub_.get(), std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, nullptr); + SetReceiveCallback(); + return 0; +} + +bool InodeS3InfoMapTool::AfterSendRequestToHost(const std::string& host) { + bool ret = false; + if (controller_->Failed()) { + errorOutput_ << "send request " + << " to metaserver: " << host + << " failed, errorcode= " << controller_->ErrorCode() + << ", error text " << controller_->ErrorText() << "\n"; + } else { + if (response_->statuscode() == metaserver::MetaStatusCode::OK) { + if (!isStreaming_) { + if (response_->s3chunkinfomap_size() == 0) { + UpdateInode2S3ChunkInfoList_( + TraslateInodeBase(requestQueue_.front()), + S3ChunkInfoList()); + } + for (auto const& list : response_->s3chunkinfomap()) { + UpdateInode2S3ChunkInfoList_( + TraslateInodeBase(requestQueue_.front()), list.second); + } + } + if (show_) { + if (isStreaming_) { + for (auto const& i : inode2S3ChunkInfoList_) { + std::cout << "fsId: " << i.first.fsid() + << " inodeId: " << i.first.inodeid() + << std::endl; + for (auto const& j : i.second.s3chunks()) { + std::cout << " s3ChunkInfo: " << j.DebugString() + << std::endl; + } + } + } else { + std::cout << "response: " << response_->DebugString() + << std::endl; + } + ret = true; + } + } else { + errorOutput_ << "request: " + << requestQueue_.front().ShortDebugString() + << " get response: " << response_->ShortDebugString() + << std::endl; + } + } + + return ret; +} + +bool InodeS3InfoMapTool::CheckRequiredFlagDefault() { + google::CommandLineFlagInfo info; + if (CheckPoolIdDefault(&info) && CheckCopysetIdDefault(&info) && + CheckPartitionIdDefault(&info) && CheckFsIdDefault(&info) && + CheckInodeIdDefault(&info)) { + std::cerr << "no -poolId=*,* -copysetId=*,* -partitionId=*,* -fsId=*,* " + "-inodeId=*,* , please use -example!" + << std::endl; + return true; + } + return false; +} + +void InodeS3InfoMapTool::SetReceiveCallback() { + receiveCallback_ = [&](butil::IOBuf* buffer) -> bool { + uint64_t chunkIndex; + InodeBase inode = TraslateInodeBase(requestQueue_.front()); + S3ChunkInfoList list; + butil::IOBuf out; + std::string delim = ":"; + // parse s3 meta stream buffer + if (buffer->cut_until(&out, delim) != 0) { + std::cerr << "invalid stream buffer: no delimiter"; + return false; + } + if (!curve::common::StringToUll(out.to_string(), &chunkIndex)) { + std::cerr << "invalid stream buffer: invalid chunkIndex"; + return false; + } + if (!brpc::ParsePbFromIOBuf(&list, *buffer)) { + std::cerr << "invalid stream buffer: invalid s3chunkinfo list"; + return false; + } + + // handle meta stream buffer + UpdateInode2S3ChunkInfoList_(inode, list); + return true; + }; +} + +void InodeS3InfoMapTool::UpdateInode2S3ChunkInfoList_(const InodeBase& inode, + const S3ChunkInfoList& list) { + auto merge = [](const S3ChunkInfoList& source, S3ChunkInfoList* target) { + for (int i = 0; i < source.s3chunks_size(); i++) { + auto* chunkinfo = target->add_s3chunks(); + *chunkinfo = source.s3chunks(i); + } + }; + + auto iter = std::find_if( + inode2S3ChunkInfoList_.begin(), inode2S3ChunkInfoList_.end(), + [inode](const std::pair& a) { + return a.first.fsid() == inode.fsid() && + a.first.inodeid() == inode.inodeid(); + }); + if (iter == inode2S3ChunkInfoList_.end()) { + inode2S3ChunkInfoList_.insert({inode, list}); + } else { + merge(list, &iter->second); + } +} + +} // namespace query +} // namespace tools +} // namespace curvefs diff --git a/curvefs/src/tools/query/curvefs_inode_s3infomap.h b/curvefs/src/tools/query/curvefs_inode_s3infomap.h new file mode 100644 index 0000000000..2c3624d109 --- /dev/null +++ b/curvefs/src/tools/query/curvefs_inode_s3infomap.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022 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: 2022-03-25 + * Author: chengyi01 + */ + +#ifndef CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_S3INFOMAP_H_ +#define CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_S3INFOMAP_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "curvefs/proto/metaserver.pb.h" +#include "curvefs/src/tools/curvefs_tool.h" +#include "curvefs/src/tools/curvefs_tool_define.h" + +namespace curvefs { +namespace tools { +namespace query { + +using curvefs::metaserver::S3ChunkInfoList; + +using HostAndResponseType = + std::vector>; + +using InodeBase = curvefs::metaserver::GetInodeRequest; + +struct HashInodeBase { + size_t operator()(const InodeBase& inode) const { + auto inodeIdHash = std::hash()(inode.inodeid()); + auto fsIdHash = std::hash()(inode.fsid()); + return inodeIdHash ^ fsIdHash; + } +}; + +struct KeyEuqalInodeBase { + bool operator()(const InodeBase& a, const InodeBase& b) const { + return a.fsid() == b.fsid() && a.inodeid() == b.inodeid(); + } +}; + +class InodeS3InfoMapTool + : public CurvefsToolRpc { + public: + explicit InodeS3InfoMapTool(const std::string& cmd = kNoInvokeCmd, + bool show = true) + : CurvefsToolRpc(cmd) { + show_ = show; + } + void PrintHelp() override; + int Init() override; + std::unordered_map + GetInode2S3ChunkInfoList() { + return inode2S3ChunkInfoList_; + } + + protected: + void AddUpdateFlags() override; + bool AfterSendRequestToHost(const std::string& host) override; + bool CheckRequiredFlagDefault() override; + void SetReceiveCallback(); + void UpdateInode2S3ChunkInfoList_(const InodeBase& inode, + const S3ChunkInfoList&list); + + protected: + std::unordered_map + inode2S3ChunkInfoList_; +}; + +} // namespace query +} // namespace tools +} // namespace curvefs + +#endif // CURVEFS_SRC_TOOLS_QUERY_CURVEFS_INODE_S3INFOMAP_H_ diff --git a/curvefs/test/tools/curvefs_umount_fs_tool_test.cpp b/curvefs/test/tools/curvefs_umount_fs_tool_test.cpp index 49b351bb1b..8fe80309ec 100644 --- a/curvefs/test/tools/curvefs_umount_fs_tool_test.cpp +++ b/curvefs/test/tools/curvefs_umount_fs_tool_test.cpp @@ -164,7 +164,7 @@ TEST_F(UmountfsToolTest, test_umount_tool_init) { channel, controller, requestQueue, response, service_stub, std::bind(&curvefs::mds::MdsService_Stub::UmountFs, service_stub.get(), std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, nullptr)); + std::placeholders::_3, nullptr), nullptr); int ret = ut_.RunCommand(); ASSERT_EQ(ret, 0);