diff --git a/conf/client.conf b/conf/client.conf index 067c7ff59..676f73094 100644 --- a/conf/client.conf +++ b/conf/client.conf @@ -1,70 +1,69 @@ #### block cache # { -# block_cache.cache_store: +# --cache_store: # cache store type, none, disk or 3fs # -# block_cache.stage_bandwidth_throttle_enable: +# --stage_bandwidth_throttle_enable: # block will been put to s3 storage directly if disk write bandwidth # exceed limit. # -# disk_cache.cache_dir: +# --cache_dir: # directory for store cache block, multi directories # and corresponding max size are supported, e.g. "/data1:200;/data2:300" # -# disk_cache.ioring_iodepth: +# --ioring_iodepth: # iodepth for io ring (works for both linux io uring and 3fs usrbio) -block_cache.cache_store=disk -block_cache.enable_stage=true -block_cache.enable_cache=true -block_cache.trace_logging=true -block_cache.upload_stage_throttle_enable=false -block_cache.upload_stage_throttle_bandwidth_mb=256 -block_cache.upload_stage_throttle_iops=100 -block_cache.upload_stage_max_inflights=32 -block_cache.prefetch_max_inflights=100 -block_cache.storage_upload_retry_timeout_s=1800 -block_cache.storage_download_retry_timeout_s=1800 - -disk_cache.cache_dir=. # __DINGOADM_TEMPLATE__ /dingofs/client/data/cache __DINGOADM_TEMPLATE__ -disk_cache.cache_size_mb=102400 -disk_cache.free_space_ratio=0.1 -disk_cache.cache_expire_s=259200 -disk_cache.cleanup_expire_interval_ms=1000 -disk_cache.ioring_iodepth=128 - -disk_state.tick_duration_s=60 -disk_state.normal2unstable_error_num=3 -disk_state.unstable2normal_succ_num=10 -disk_state.unstable2down_s=1800 -disk_state.check_duration_ms=3000 +--cache_store=disk +--enable_stage=true +--enable_cache=true +--cache_trace_logging=true +--upload_stage_throttle_enable=false +--upload_stage_throttle_bandwidth_mb=256 +--upload_stage_throttle_iops=100 +--upload_stage_max_inflights=32 +--prefetch_max_inflights=100 +--storage_upload_retry_timeout_s=1800 +--storage_download_retry_timeout_s=1800 + +--cache_dir=. +--cache_size_mb=102400 +--free_space_ratio=0.1 +--cache_expire_s=259200 +--cleanup_expire_interval_ms=1000 +--ioring_iodepth=128 + +--disk_state_tick_duration_s=60 +--disk_state_normal2unstable_error_num=3 +--disk_state_unstable2normal_succ_num=10 +--disk_state_unstable2down_s=1800 +--disk_state_check_duration_ms=3000 # } #### remote cache # { -remote_cache.cache_group= -remote_cache.mds_addrs=127.0.0.1:6900 -remote_cache.mds_rpc_timeout_ms=3000 -remote_cache.mds_rpc_retry_times=1 -remote_cache.mds_request_retry_times=3 -remote_cache.load_members_interval_ms=1000 - -remote_cache.fill_group_cache=true -remote_cache.subrequest_range_size=1048576 -remote_cache.rpc_connect_timeout_ms=1000 -remote_cache.rpc_connect_timeout_as_unreachable=10 -remote_cache.rpc_max_connection_pool_size=256 -remote_cache.put_rpc_timeout_ms=30000 -remote_cache.range_rpc_timeout_ms=30000 -remote_cache.cache_rpc_timeout_ms=30000 -remote_cache.prefetch_rpc_timeout_ms=3000 -remote_cache.ping_rpc_timeout_ms=1000 -remote_cache.rpc_max_retry_time=3 -remote_cache.rpc_max_timeout_ms=60000 - -cache_node_state.tick_duration_s=30 -cache_node_state.normal2unstable_error_num=10 -cache_node_state.unstable2normal_succ_num=3 -cache_node_state.check_duration_ms=3000 +--cache_group= +--mds_rpc_timeout_ms=3000 +--mds_rpc_retry_times=1 +--mds_request_retry_times=3 +--load_members_interval_ms=1000 + +--fill_group_cache=true +--subrequest_range_size=1048576 +--rpc_connect_timeout_ms=1000 +--rpc_connect_timeout_as_unreachable=10 +--rpc_max_connection_pool_size=256 +--put_rpc_timeout_ms=30000 +--range_rpc_timeout_ms=30000 +--cache_rpc_timeout_ms=30000 +--prefetch_rpc_timeout_ms=3000 +--ping_rpc_timeout_ms=1000 +--rpc_max_retry_time=3 +--rpc_max_timeout_ms=60000 + +--cache_node_state_tick_duration_s=30 +--cache_node_state_normal2unstable_error_num=10 +--cache_node_state_unstable2normal_succ_num=3 +--cache_node_state_check_duration_ms=3000 # } #### control fuse module @@ -80,115 +79,102 @@ cache_node_state.check_duration_ms=3000 # but there might be a kernel issue that will cause kernel panic when enabling it # see https://lore.kernel.org/all/CAAmZXrsGg2xsP1CK+cbuEMumtrqdvD-NKnWzhNcvn71RV3c1yw@mail.gmail.com/ # until this issue has been fixed, splice should be disabled -fuse.conn_info.want_splice_move=false -fuse.conn_info.want_splice_read=false -fuse.conn_info.want_splice_write=false -fuse.conn_info.want_auto_inval_data=true -fuse.file_info.direct_io=false -fuse.file_info.keep_cache=true +--fuse_conn_info_want_splice_move=false +--fuse.conn_info_want_splice_read=false +--fuse.conn_info_want_splice_write=false +--fuse_conn_info_want_auto_inval_data=true +--fuse_file_info_direct_io=false +--fuse_file_info_keep_cache=true # } #### Memrory page allocator # { # -data_stream.page.size=65536 -data_stream.page.total_size_mb=1024 -data_stream.page.use_pool=true +--data_stream_page.size=65536 +--data_stream_page.total_size_mb=1024 +--data_stream_page.use_pool=true # } #### aws sdk # { # -s3.region=us-east-1 -s3.useVirtualAddressing=false +--s3_region=us-east-1 +--s3_use_virtual_address=false # Off = 0,Fatal = 1,Error = 2,Warn = 3,Info = 4,Debug = 5,Trace = 6 -s3.logLevel=4 -s3.verify_SSL=False -s3.maxConnections=32 -s3.connectTimeout=60000 -s3.requestTimeout=10000 -s3.use_crt_client=true +--s3_loglevel=4 +--s3_verify_ssl=False +--s3_max_connections=32 +--s3_connect_timeout=60000 +--s3_request_timeout=10000 +--s3.use_crt_client=true # this only work when use_crt_client is false -s3.use_thread_pool=false +--s3_use_thread_pool=false # this only work when use_crt_client is false and use_thread_pool is true -s3.async_thread_num_in_thread_pool=256 -s3.enableTelemetry=false +--s3_async_thread_num=256 +--s3_enable_telemetry=false # } #### block throttle # { # -s3.throttle.iopsTotalLimit=0 -s3.throttle.iopsReadLimit=0 -s3.throttle.iopsWriteLimit=0 -s3.throttle.bpsTotalMB=0 -s3.throttle.bpsReadMB=0 -s3.throttle.bpsWriteMB=0 +--iops_total_limit=0 +--iops_read_limit=0 +--iops_write_limit=0 +--io_bandwidth_total_mb=0 +--io_bandwidth_read_mb=0 +--io_bandwidth_write_mb=0 # limit all inflight async requests' bytes, |0| means not limited -s3.maxAsyncRequestInflightBytes=104857600 +--io_max_inflight_async_bytes=104857600 # } #### log related # { # -client.common.logDir=/data/logs/dingofs # __DINGOADM_TEMPLATE__ /dingofs/client/logs __DINGOADM_TEMPLATE__ +--client_log_dir=/data/logs/dingofs # as the number increases, it becomes more and more detailed -client.loglevel=0 +--client_log_level=0 # } -#### brpc -# { -# -# close socket after defer.close.second -rpc.defer.close.second=1 -# rpc health check interval in second, 0 or negative value means disable health check -rpc.healthCheckIntervalSec=3 -# } - -mds.addr=172.20.61.102:7801 - -### uds -uds.fdCommPath=/var/run # unix domain socket file path +### unix domain socket file path +--socket_path=/var/run/ ### block access related options - -block_access.rados.rados_op_timeout=120 +--rados_op_timeout=120 ### vfs data related options # vfs.data.writeback_suffix: # file with the specified suffix will use writeback write policy, # multi suffixs supported, e.g. .pt:.ckpt -vfs.data.writeback_suffix= -vfs.data.writeback=false -vfs.data.flush_bg_thread=16 -vfs.data.vfs_periodic_flush_interval_ms=100 +--vfs_data_writeback_suffix= +--vfs_data_writeback=false +--client_vfs_flush_bg_thread=16 +--client_vfs_periodic_flush_interval_ms=100 -vfs.data.single_tread_read=false -# only work when vfs.data.single_thread_read is false -vfs.data.read_executor_thread=8 +--client_vfs_read_executor_thread=8 #prefetch config -vfs.prefetch.blocks=1 -vfs.prefetch.threads=8 +--client_vfs_prefetch_blocks=1 +--client_vfs_prefetch_threads=8 # warmup config -vfs.warmup.threads=4 -vfs.intime_warmup.enbale=false -vfs.intime_warmup.restart_mtime_interval_secs=120 #2min -vfs.intime_warmup.restart_trigger_interval_secs=1800 #30min +--client_vfs_warmup_threads=4 +--client_vfs_intime_warmup_enable=false +--client_vfs_warmup_mtime_restart_interval_secs=120 +--client_vfs_warmup_trigger_restart_interval_secs=1800 + ### vfs meta related options -vfs.meta.max_name_length=255 # max length of file name +--vfs_meta_max_name_length=255 # Default 0, the worker num of bthread whill be #cpu-cores -vfs.bthread_worker_num=0 -vfs.dummy_server.port=10000 +--client_bthread_worker_num=0 +--vfs_dummy_server_port=10000 # related loggging -vfs.access_logging=true -vfs.access_log_threshold_us=0 -vfs.vfs_meta_logging=true -vfs.vfs_meta_log_threshold_us=1000 +--client_access_logging=true +--client_access_log_threshold_us=0 +--client_vfs_meta_logging=true +--client_vfs_meta_log_threshold_us=1000 -vfs.trace_logging=false +--trace_logging=false diff --git a/src/cache/benchmark/CMakeLists.txt b/src/cache/benchmark/CMakeLists.txt index 66b715ff1..fd41ef535 100644 --- a/src/cache/benchmark/CMakeLists.txt +++ b/src/cache/benchmark/CMakeLists.txt @@ -27,6 +27,7 @@ target_link_libraries(cache_benchmark cache_utils cache_common cache_storage + cache_tiercache ) add_executable(cache-bench main.cc) diff --git a/src/cache/cachegroup/cache_group_node_server.cc b/src/cache/cachegroup/cache_group_node_server.cc index d6a919fc4..ed92e48b3 100644 --- a/src/cache/cachegroup/cache_group_node_server.cc +++ b/src/cache/cachegroup/cache_group_node_server.cc @@ -25,6 +25,7 @@ #include "cache/cachegroup/cache_group_node.h" #include "cache/cachegroup/cache_group_node_service.h" #include "cache/common/macro.h" +#include "common/options/cache.h" namespace brpc { DECLARE_bool(graceful_quit_on_sigterm); diff --git a/src/cache/common/mds_client.cc b/src/cache/common/mds_client.cc index 165cbeb0f..2425c96b8 100644 --- a/src/cache/common/mds_client.cc +++ b/src/cache/common/mds_client.cc @@ -46,7 +46,7 @@ namespace dingofs { namespace cache { -DEFINE_string(mds_addrs, "", +DEFINE_string(mds_addrs, "127.0.0.1:7400", "Cache group member manager service rpc addresses"); DEFINE_validator(mds_addrs, Helper::NonEmptyString); diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index f9b406dc4..e03e98916 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -29,6 +29,7 @@ target_link_libraries(fuse_client_lib dingofs_metrics dingofs_common client_options + cache_tiercache jsoncpp ${FUSE3_LIBRARY} diff --git a/src/client/common/client_option.h b/src/client/common/client_option.h new file mode 100644 index 000000000..c7d398467 --- /dev/null +++ b/src/client/common/client_option.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2025 dingodb.com, Inc. All Rights Reserved + * + * 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. + */ + +#ifndef DINGOFS_CLIENT_COMMON_CLIENT_OPTION_H_ +#define DINGOFS_CLIENT_COMMON_CLIENT_OPTION_H_ + +#include +#include + +#include + +#include "common/blockaccess/accesser_common.h" +#include "common/const.h" +#include "common/options/client.h" + +namespace dingofs { +namespace client { + +// fuse option +struct FuseConnInfo { + bool want_splice_move; + bool want_splice_read; + bool want_splice_write; + bool want_auto_inval_data; +}; + +struct FuseFileInfo { + bool keep_cache; +}; + +struct FuseOption { + FuseConnInfo conn_info; + FuseFileInfo file_info; +}; + +// memory option +struct PageOption { + uint32_t page_size; + uint64_t total_size; + bool use_pool; +}; + +// vfs option +struct VFSMetaOption { + uint32_t max_name_length; // max length of file name +}; + +struct VFSDataOption { + bool writeback{false}; // whether to use writeback + std::string writeback_suffix; +}; + +struct VFSOption { + blockaccess::BlockAccessOptions block_access_opt; // from gflags + PageOption page_option; + FuseOption fuse_option; + + VFSMetaOption meta_option; + VFSDataOption data_option; + + uint32_t dummy_server_port{10000}; +}; + +static void InitFuseOption(FuseOption* option) { + { // fuse conn info + auto* fuse_conn_info = &option->conn_info; + fuse_conn_info->want_splice_move = FLAGS_fuse_conn_info_want_splice_move; + fuse_conn_info->want_splice_read = FLAGS_fuse_conn_info_want_splice_read; + fuse_conn_info->want_splice_write = FLAGS_fuse_conn_info_want_splice_write; + fuse_conn_info->want_auto_inval_data = + FLAGS_fuse_conn_info_want_auto_inval_data; + } + + { // fuse file info + auto* fuse_file_info = &option->file_info; + fuse_file_info->keep_cache = FLAGS_fuse_file_info_keep_cache; + } +} + +static void InitMemoryPageOption(PageOption* option) { + // page option + option->page_size = FLAGS_data_stream_page_size; + option->total_size = FLAGS_data_stream_page_total_size_mb; + option->use_pool = FLAGS_data_stream_page_use_pool; + + if (option->page_size == 0) { + CHECK(false) << "page size must greater than 0."; + } + + option->total_size = option->total_size * kMiB; + if (option->total_size < 64 * kMiB) { + CHECK(false) << "page total size must greater than 64MB."; + } +} + +static void InitVFSMetaOption(VFSMetaOption* option) { + option->max_name_length = FLAGS_vfs_meta_max_name_length; + if (option->max_name_length < 1) { + CHECK(false) << "file name length must greater than 0."; + } +} + +static void InitVFSDataOption(VFSDataOption* option) { + option->writeback = FLAGS_vfs_data_writeback; + option->writeback_suffix = FLAGS_vfs_data_writeback_suffix; +} + +static void InitVFSOption(VFSOption* option) { + blockaccess::InitAwsSdkConfig( + &option->block_access_opt.s3_options.aws_sdk_config); + blockaccess::InitBlockAccesserThrottleOptions( + &option->block_access_opt.throttle_options); + + InitMemoryPageOption(&option->page_option); + + InitFuseOption(&option->fuse_option); + + InitVFSMetaOption(&option->meta_option); + + InitVFSDataOption(&option->data_option); + + option->dummy_server_port = FLAGS_vfs_dummy_server_port; +} + +} // namespace client +} // namespace dingofs + +#endif // DINGOFS_CLIENT_COMMON_CLIENT_OPTION_H_ diff --git a/src/client/common/global_log.h b/src/client/common/global_log.h index 5e45c55bf..a33d6d249 100644 --- a/src/client/common/global_log.h +++ b/src/client/common/global_log.h @@ -18,30 +18,12 @@ #define DINGOFS_SRC_CLIENT_COMMON_GLOBAL_LOG_H_ #include "common/options/client.h" -#include "fmt/format.h" #include "glog/logging.h" -#include "utils/configuration.h" -#include "utils/gflags_helper.h" - -static int InitLog(const char* argv0, const std::string& conf_path) { - dingofs::utils::Configuration conf; - conf.SetConfigPath(conf_path); - if (!conf.LoadConfig()) { - LOG(ERROR) << "loadConfig fail, confPath=" << conf_path; - return 1; - } +static int InitLog(const char* argv0) { // set log dir - if (FLAGS_log_dir.empty()) { - if (!conf.GetStringValue("client.common.logDir", &FLAGS_log_dir)) { - LOG(WARNING) << fmt::format( - "no client.common.logDir in {}, will log to /tmp.", conf_path); - } - } - - dingofs::utils::GflagsLoadValueFromConfIfCmdNotSet dummy; - dummy.Load(&conf, "v", "client.loglevel", &FLAGS_v); - dingofs::client::FLAGS_vlog_level = FLAGS_v; + FLAGS_log_dir = dingofs::client::FLAGS_client_log_dir; + FLAGS_v = dingofs::client::FLAGS_client_log_level; FLAGS_logbufsecs = 0; FLAGS_minloglevel = google::GLOG_INFO; @@ -49,6 +31,8 @@ static int InitLog(const char* argv0, const std::string& conf_path) { // initialize logging module google::InitGoogleLogging(argv0); + LOG(INFO) << "current verbose logging level is: " << FLAGS_v + << ", log dir is: " << FLAGS_log_dir; return 0; } diff --git a/src/client/common/utils.h b/src/client/common/utils.h index 49b57f66e..ca4e83e00 100644 --- a/src/client/common/utils.h +++ b/src/client/common/utils.h @@ -28,6 +28,18 @@ static std::string Char2Addr(const char* p) { return oss.str(); } +inline bool ParseMetaURL(const std::string& meta_url, std::string& addrs, + std::string& fs_name) { + size_t pos = meta_url.find('/'); + if (pos == std::string::npos) { + return false; + } + addrs = meta_url.substr(0, pos); + fs_name = meta_url.substr(pos + 1); + + return true; +} + } // namespace client } // namespace dingofs diff --git a/src/client/fuse/fuse_common.h b/src/client/fuse/fuse_common.h index a55c0c582..43cad1a99 100644 --- a/src/client/fuse/fuse_common.h +++ b/src/client/fuse/fuse_common.h @@ -46,31 +46,13 @@ using dingofs::utils::TrimSpace; const std::string kFdCommPathKey = "fd_comm_path"; -#ifdef __cplusplus -extern "C" { -#endif - struct MountOption { - const char* mount_point; - const char* fs_name; - const char* fs_type; - char* conf; - char* mds_addr; + std::string mount_point; + std::string fs_name; + std::string fs_type; + std::string mds_addrs; }; -static const struct fuse_opt kMountOpts[] = { - {"fsname=%s", offsetof(struct MountOption, fs_name), 0}, - - {"fstype=%s", offsetof(struct MountOption, fs_type), 0}, - - {"conf=%s", offsetof(struct MountOption, conf), 0}, - - FUSE_OPT_END}; - -#ifdef __cplusplus -} // extern "C" -#endif - inline int FuseAddOpts(struct fuse_args* args, const char* arg_value) { if (fuse_opt_add_arg(args, "-o") == -1) return 1; if (fuse_opt_add_arg(args, arg_value) == -1) return 1; @@ -78,10 +60,10 @@ inline int FuseAddOpts(struct fuse_args* args, const char* arg_value) { } // Get file inode number -inline int GetFileInode(const char* file_name) { +inline int GetFileInode(const std::string& file_name) { struct stat file_info; - if (stat(file_name, &file_info) == 0) { + if (stat(file_name.c_str(), &file_info) == 0) { return file_info.st_ino; } return -1; @@ -161,7 +143,7 @@ inline std::string GetFdCommFileName(const std::string& filename) { * * @param mountpoint dingo-fuse mountpoint */ -inline bool CanShutdownGracefully(const char* mountpoint) { +inline bool CanShutdownGracefully(const std::string& mountpoint) { if (GetFileInode(mountpoint) != dingofs::ROOTINODEID) { return false; } @@ -175,7 +157,7 @@ inline bool CanShutdownGracefully(const char* mountpoint) { * @param mountpoint dingo-fuse mountpoint * @param fd file descriptor for /dev/fuse */ -inline void DingoSessionUnmount(const char* mountpoint, int fd) { +inline void DingoSessionUnmount(const std::string& mountpoint, int fd) { int res; if (fd != -1) { @@ -198,7 +180,7 @@ inline void DingoSessionUnmount(const char* mountpoint, int fd) { if (res == 1 && (pfd.revents & POLLERR)) return; } - res = umount2(mountpoint, 2); + res = umount2(mountpoint.c_str(), 2); if (res == 0) return; } diff --git a/src/client/fuse/fuse_op.cc b/src/client/fuse/fuse_op.cc index eab789386..6a9350175 100644 --- a/src/client/fuse/fuse_op.cc +++ b/src/client/fuse/fuse_op.cc @@ -26,7 +26,6 @@ #include #include "absl/strings/str_format.h" -#include "client/common/utils.h" #include "client/vfs/common/helper.h" #include "client/vfs/data_buffer.h" #include "client/vfs/vfs_meta.h" @@ -36,13 +35,12 @@ #include "common/status.h" #include "fmt/format.h" #include "glog/logging.h" -#include "utils/configuration.h" static dingofs::client::vfs::VFSWrapper* g_vfs = nullptr; -USING_FLAG(client_fuse_file_info_direct_io) -USING_FLAG(client_fuse_file_info_keep_cache) -USING_FLAG(client_fuse_enable_readdir_cache) +USING_FLAG(fuse_file_info_direct_io) +USING_FLAG(fuse_file_info_keep_cache) +USING_FLAG(fuse_enable_readdir_cache) using dingofs::Status; using dingofs::client::vfs::Attr; @@ -310,9 +308,9 @@ static void ReplyStatfs(fuse_req_t req, const FsStat& stat) { int InitFuseClient(const char* argv0, const struct MountOption* mount_option) { dingofs::client::vfs::VFSConfig config = { + .mds_addrs = mount_option->mds_addrs, .mount_point = mount_option->mount_point, .fs_name = mount_option->fs_name, - .config_path = mount_option->conf, .fs_type = mount_option->fs_type, }; @@ -495,10 +493,9 @@ void FuseOpOpen(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fi->fh = fh; fi->direct_io = - (dingofs::IsInternalNode(ino) || FLAGS_client_fuse_file_info_direct_io) - ? 1 - : 0; - fi->keep_cache = FLAGS_client_fuse_file_info_keep_cache ? 1 : 0; + (dingofs::IsInternalNode(ino) || FLAGS_fuse_file_info_direct_io) ? 1 + : 0; + fi->keep_cache = FLAGS_fuse_file_info_keep_cache ? 1 : 0; ReplyOpen(req, fi); } @@ -584,9 +581,8 @@ void FuseOpOpenDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { } else { fi->fh = fh; - fi->cache_readdir = - (need_cache && FLAGS_client_fuse_enable_readdir_cache) ? 1 : 0; - fi->keep_cache = FLAGS_client_fuse_enable_readdir_cache ? 1 : 0; + fi->cache_readdir = (need_cache && FLAGS_fuse_enable_readdir_cache) ? 1 : 0; + fi->keep_cache = FLAGS_fuse_enable_readdir_cache ? 1 : 0; ReplyOpen(req, fi); } @@ -824,11 +820,11 @@ void FuseOpCreate(fuse_req_t req, fuse_ino_t parent, const char* name, } else { fi->fh = fh; - fi->direct_io = (dingofs::IsInternalNode(attr.ino) || - FLAGS_client_fuse_file_info_direct_io) - ? 1 - : 0; - fi->keep_cache = FLAGS_client_fuse_file_info_keep_cache ? 1 : 0; + fi->direct_io = + (dingofs::IsInternalNode(attr.ino) || FLAGS_fuse_file_info_direct_io) + ? 1 + : 0; + fi->keep_cache = FLAGS_fuse_file_info_keep_cache ? 1 : 0; ReplyCreate(req, fi, attr); } diff --git a/src/client/fuse/fuse_parse.h b/src/client/fuse/fuse_parse.h deleted file mode 100644 index 085ff2b3f..000000000 --- a/src/client/fuse/fuse_parse.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2024 dingodb.com, Inc. All Rights Reserved - * - * 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. - */ -#include - -#include -#include -#include - -#include "client/fuse/fuse_common.h" -#include "utils/string.h" - -using dingofs::utils::TrimSpace; - -inline void PrintOptionHelp(const char* o, const char* msg) { - printf(" -o %-20s%s\n", o, msg); -} - -inline void ExtraOptionsHelp() { - printf("\nExtra options:\n"); - PrintOptionHelp("fsname", "[required] name of filesystem to be mounted"); - PrintOptionHelp("fstype", - "[required] type of filesystem to be mounted (s3/volume)"); - PrintOptionHelp("conf", "[required] path of config file"); - printf(" --mdsAddr mdsAddr of dingofs cluster\n"); -} - -inline std::string MatchAnyPattern( - const std::unordered_map& patterns, const char* src) { - size_t src_len = strlen(src); - for (const auto& pair : patterns) { - const auto& pattern = pair.first; - if (pattern.length() < src_len && - strncmp(pattern.c_str(), src, pattern.length()) == 0) { - return pattern; - } - } - return {}; -} - -inline void ParseOption(int argc, char** argv, int* parsed_argc_p, - char** parsed_argv, struct MountOption* opts) { - // add support for parsing option value with comma(,) - std::unordered_map patterns = { - {"--mdsaddr=", &opts->mds_addr}}; - for (int i = 0, j = 0; j < argc; j++) { - std::string p = MatchAnyPattern(patterns, argv[j]); - int p_len = p.length(); - int src_len = strlen(argv[j]); - if (p_len) { - if (*patterns[p]) { - free(*patterns[p]); - } - *patterns[p] = - reinterpret_cast(malloc(sizeof(char) * (src_len - p_len + 1))); - memcpy(*patterns[p], argv[j] + p_len, src_len - p_len); - (*patterns[p])[src_len - p_len] = '\0'; - *parsed_argc_p = *parsed_argc_p - 1; - } else { - parsed_argv[i] = - reinterpret_cast(malloc(sizeof(char) * (src_len + 1))); - memcpy(parsed_argv[i], argv[j], src_len); - parsed_argv[i][src_len] = '\0'; - i++; - } - } -} - -inline void FreeParsedArgv(char** parsed_argv, int alloc_size) { - for (int i = 0; i < alloc_size; i++) { - free(parsed_argv[i]); - } - free((char*)parsed_argv); -} diff --git a/src/client/fuse/fuse_server.cc b/src/client/fuse/fuse_server.cc index cef1e3d06..4d12e53b4 100644 --- a/src/client/fuse/fuse_server.cc +++ b/src/client/fuse/fuse_server.cc @@ -16,19 +16,20 @@ #include "client/fuse/fuse_server.h" +#include #include #include +#include #include "absl/cleanup/cleanup.h" #include "client/fuse/fuse_common.h" #include "client/fuse/fuse_lowlevel_ops_func.h" -#include "client/fuse/fuse_parse.h" #include "client/fuse/fuse_passfd.h" #include "client/fuse/fuse_upgrade_manager.h" #include "common/options/client.h" -#include "common/version.h" #include "fmt/format.h" +#include "fuse_opt.h" #include "glog/logging.h" #include "utils/concurrent/concurrent.h" @@ -43,28 +44,36 @@ USING_FLAG(client_fuse_fd_get_retry_interval_ms) USING_FLAG(client_fuse_check_alive_max_retries) USING_FLAG(client_fuse_check_alive_retry_interval_ms) +// fuse mount options +DEFINE_string(fuse_mount_options, "default_permissions,allow_other", + "mount options for libfuse"); +DEFINE_bool(fuse_use_single_thread, false, "use single thread for libfuse"); +DEFINE_validator(fuse_use_single_thread, brpc::PassValidate); +DEFINE_bool(fuse_use_clone_fd, false, "use clone fd for libfuse"); +DEFINE_validator(fuse_use_clone_fd, brpc::PassValidate); +DEFINE_uint32(fuse_max_threads, 10, "max threads for libfuse"); +DEFINE_validator(fuse_max_threads, brpc::PassValidate); + +DEFINE_string(socket_path, "/var/run", + "path for store unix domain socket file"); + FuseServer::FuseServer() = default; -int FuseServer::Init(int argc, char* argv[], struct MountOption* mount_option) { - argc_ = argc; - argv_ = argv; +int FuseServer::Init(const std::string& program_name, + struct MountOption* mount_option) { mount_option_ = mount_option; - - program_name_ = argv[0]; - int parsed_argc = argc_; - parsed_argv_ = reinterpret_cast(malloc(sizeof(char*) * argc_)); - ParseOption(argc_, argv_, &parsed_argc, parsed_argv_, mount_option_); - // init fuse args - args_ = FUSE_ARGS_INIT(parsed_argc, parsed_argv_); + program_name_ = program_name; AllocateFuseInitBuf(); - if (ParseCmdLine() == 1) return 1; - if (OptParse() == 1) return 1; + if (AddMountOptions() == 1) return 1; config_ = fuse_loop_cfg_create(); CHECK(config_ != nullptr) << "fuse_loop_cfg_create fail."; + fd_comm_file_ = + absl::StrFormat("%s/fd_comm_socket.%d", FLAGS_socket_path, getpid()); + return 0; } @@ -72,8 +81,6 @@ FuseServer::~FuseServer() { unlink(fd_comm_file_.c_str()); FreeFuseInitBuf(); - free(opts_.mountpoint); - FreeParsedArgv(parsed_argv_, argc_); fuse_opt_free_args(&args_); if (config_ != nullptr) { @@ -180,65 +187,26 @@ void FuseServer::UdsServerStart() { LOG(INFO) << "dingo-fuse uds server started."; } -int FuseServer::ParseCmdLine() { - if (fuse_parse_cmdline(&args_, &opts_) != 0) return 1; - - if (opts_.show_help) { - printf( - "usage: %s -o conf=/etc/dingofs/client.conf -o fsname=dingofs \\\n" - " -o fstype=s3 " - "[--mdsaddr=172.20.1.10:6700,172.20.1.11:6700,172.20.1.12:6700] \\\n" - " [OPTIONS] \n", - program_name_); - printf("Fuse Options:\n"); - fuse_cmdline_help(); - fuse_lowlevel_help(); - ExtraOptionsHelp(); - return 1; - - } else if (opts_.show_version) { - dingofs::ShowVerion(); - - printf("FUSE library version %s\n", fuse_pkgversion()); - fuse_lowlevel_version(); - return 1; - } - - if (opts_.mountpoint == nullptr) { - printf("required option[mountpoint] is missing.\n"); - return 1; - } - - return 0; -} - -int FuseServer::OptParse() { - if (fuse_opt_parse(&args_, mount_option_, kMountOpts, nullptr) == -1) { - return 1; - } - mount_option_->mount_point = opts_.mountpoint; - - if (mount_option_->conf == nullptr || mount_option_->fs_name == nullptr || - mount_option_->fs_type == nullptr) { - printf("one of required options[conf|fsname|fstype] is missing.\n"); - return 1; - } +int FuseServer::AddMountOptions() { + CHECK(!program_name_.empty()) << "program_name_ should not be empty"; + if (fuse_opt_add_arg(&args_, program_name_.c_str()) != 0) return 1; // Values shown in "df -T" and friends first column "Filesystem",DindoFS + // filesystem name - FuseAddOpts(&args_, (const char*)"subtype=dingofs"); - std::string arg_value; - arg_value.append("fsname=DingoFS"); - arg_value.append(":"); - arg_value.append(mount_option_->fs_name); - FuseAddOpts(&args_, arg_value.c_str()); + if (FuseAddOpts(&args_, (const char*)"subtype=dingofs") != 0) return 1; + + std::string arg_value = + fmt::format("fsname=DingoFS:{}", mount_option_->fs_name); + if (FuseAddOpts(&args_, arg_value.c_str()) != 0) return 1; + + if (FuseAddOpts(&args_, "default_permissions,allow_other") != 0) return 1; return 0; } int FuseServer::CreateSession() { // create fuse new session - session_ = fuse_session_new(&args_, &kFuseOp, sizeof(kFuseOp), mount_option_); + session_ = fuse_session_new(&args_, &kFuseOp, sizeof(kFuseOp), nullptr); if (session_ == nullptr) return 1; // install fuse signal @@ -257,14 +225,16 @@ void FuseServer::DestroySsesion() { } int FuseServer::SessionMount() { - printf("Begin to mount fs %s to %s\n", mount_option_->fs_name, - mount_option_->mount_point); + std::cout << fmt::format("Begin to mount fs {} to {}\n", + mount_option_->fs_name, mount_option_->mount_point); + LOG(INFO) << fmt::format("Begin to mount fs {} to {}.", + mount_option_->fs_name, mount_option_->mount_point); - if (CanShutdownGracefully(opts_.mountpoint)) { - bool is_shutdown = ShutdownGracefully(opts_.mountpoint); + if (CanShutdownGracefully(mount_option_->mount_point)) { + bool is_shutdown = ShutdownGracefully(mount_option_->mount_point); if (!is_shutdown) { LOG(ERROR) << "smooth upgrade failed, can't mount on: " - << opts_.mountpoint; + << mount_option_->mount_point; return 1; } LOG(INFO) << "old dingo-fuse is already shutdown"; @@ -280,7 +250,8 @@ int FuseServer::SessionMount() { return 0; } - if (fuse_session_mount(session_, opts_.mountpoint) != 0) return 1; + if (fuse_session_mount(session_, mount_option_->mount_point.c_str()) != 0) + return 1; return 0; } @@ -331,12 +302,12 @@ int FuseServer::SessionLoop() { } // process user request - if (opts_.singlethread) { + if (FLAGS_fuse_use_single_thread) { return fuse_session_loop(session_); } - fuse_loop_cfg_set_clone_fd(config_, opts_.clone_fd); - fuse_loop_cfg_set_max_threads(config_, opts_.max_threads); + fuse_loop_cfg_set_clone_fd(config_, FLAGS_fuse_use_clone_fd); + fuse_loop_cfg_set_max_threads(config_, FLAGS_fuse_max_threads); return fuse_session_loop_mt(session_, config_); } @@ -346,19 +317,16 @@ void FuseServer::ExportMetrics(const std::string& key, fd_comm_metrics_.expose(butil::StringPiece(key)); } -int FuseServer::Serve(const std::string& fd_comm_path) { - fd_comm_file_ = - absl::StrFormat("%s/fd_comm_socket.%d", fd_comm_path, getpid()); - +int FuseServer::Serve() { // export fd_comm_path value for new dingo-fuse use ExportMetrics(kFdCommPathKey, fd_comm_file_); UdsServerStart(); - fuse_daemonize(opts_.foreground); + fuse_daemonize(1); LOG(INFO) << fmt::format( "dingo-fuse start loop, singlethread={} max_threads={}.", - opts_.singlethread, opts_.max_threads); + FLAGS_fuse_use_single_thread, FLAGS_fuse_max_threads); if (SaveOpInitMsg() == 1) { LOG(ERROR) << "save fuse init message failed"; @@ -385,7 +353,7 @@ void FuseServer::SessionUnmount() { // DingoSessionUnmount instead of fuse_session_unmount because // session_->mountpoint is nullptr LOG(INFO) << "use DingoSessionUnmount"; - DingoSessionUnmount(opts_.mountpoint, GetDevFd()); + DingoSessionUnmount(mount_option_->mount_point, GetDevFd()); } else { LOG(INFO) << "use fuse_session_unmount"; fuse_session_unmount(session_); @@ -393,7 +361,7 @@ void FuseServer::SessionUnmount() { } // TODO: check the fstype to determain the dingo-fuse -bool FuseServer::ShutdownGracefully(const char* mountpoint) { +bool FuseServer::ShutdownGracefully(const std::string& mountpoint) { // get old dingo-fuse pid std::string file_name = absl::StrFormat("%s/%s", mountpoint, dingofs::STATSNAME); diff --git a/src/client/fuse/fuse_server.h b/src/client/fuse/fuse_server.h index 711df3fb2..3b0939354 100644 --- a/src/client/fuse/fuse_server.h +++ b/src/client/fuse/fuse_server.h @@ -34,11 +34,9 @@ class FuseServer { FuseServer(const FuseServer&) = delete; FuseServer& operator=(const FuseServer&) = delete; - int Init(int argc, char* argv[], struct MountOption* mount_option); + int Init(const std::string& program_name, struct MountOption* mount_option); - int ParseCmdLine(); - - int OptParse(); + int AddMountOptions(); int CreateSession(); @@ -48,7 +46,7 @@ class FuseServer { void SessionUnmount(); - int Serve(const std::string& fd_comm_path); + int Serve(); void Shutdown(); @@ -67,20 +65,16 @@ class FuseServer { int SessionLoop(); - bool ShutdownGracefully(const char* mountpoint); + bool ShutdownGracefully(const std::string& mountpoint); void UdsServerStart(); void ExportMetrics(const std::string& key, const std::string& value); - int argc_{0}; - char** argv_ = {nullptr}; - char** parsed_argv_ = {nullptr}; - const char* program_name_{nullptr}; + std::string program_name_; // libfuse - struct fuse_args args_{0}; - struct fuse_cmdline_opts opts_{0}; + struct fuse_args args_{0, nullptr, 0}; struct fuse_session* session_{nullptr}; struct fuse_loop_config* config_{nullptr}; struct MountOption* mount_option_{nullptr}; diff --git a/src/client/main.cc b/src/client/main.cc index 498499214..9aceea897 100644 --- a/src/client/main.cc +++ b/src/client/main.cc @@ -14,18 +14,21 @@ * limitations under the License. */ +#include + #include #include #include "absl/cleanup/cleanup.h" #include "client/common/global_log.h" +#include "client/common/utils.h" #include "client/fuse/fuse_op.h" #include "client/fuse/fuse_server.h" +#include "common/flag.h" +#include "common/options/cache.h" #include "common/options/client.h" -#include "utils/configuration.h" using FuseServer = dingofs::client::fuse::FuseServer; -using Configuration = dingofs::utils::Configuration; static FuseServer* fuse_server = nullptr; @@ -53,23 +56,65 @@ static int InstallSignal(int sig, void (*handler)(int)) { return 0; } -int main(int argc, char* argv[]) { - struct MountOption mount_option { - nullptr - }; +static dingofs::FlagExtraInfo extras = { + .program = "dingo-fuse", + .usage = "dingo-fuse [OPTIONS] ", + .examples = + R"(dingo-fuse 10.220.69.10:7400/dingofs /mnt/dingofs +dingo-fuse --client_log_dir=/mnt/logs 10.220.32.1:6700/dingofs /mnt/dingofs +dingo-fuse --flagfile client.conf 10.220.32.1:6700/dingofs /mnt/dingofs +)", + .patterns = {"src/client", "cache/tiercache", "cache/blockcache", + "cache/remotecache", "options/blockaccess", "options/client"}, +}; +int main(int argc, char* argv[]) { + // install singal handler InstallSignal(SIGHUP, HandleSignal); + // parse gflags + int rc = dingofs::ParseFlags(&argc, &argv, extras); + if (rc != 0) { + return EXIT_FAILURE; + } + + // after parsing: + // argv[0] is program name + // argv[1] is meta url + // argv[2] is mount point + if (argc < 3) { + std::cerr << "missing meta url or mount point.\n"; + std::cerr << "Usage: " << extras.usage << '\n'; + return EXIT_FAILURE; + } + + std::string mds_addrs; + std::string fs_name; + if (!dingofs::client::ParseMetaURL(argv[1], mds_addrs, fs_name)) { + std::cerr << "meta url is invalid: " << argv[1] << '\n'; + return EXIT_FAILURE; + } + // used for remote cache + dingofs::cache::FLAGS_mds_addrs = mds_addrs; + + struct MountOption mount_option{.mount_point = argv[2], + .fs_name = fs_name, + .fs_type = dingofs::client::FLAGS_fstype, + .mds_addrs = mds_addrs}; + fuse_server = new FuseServer(); if (fuse_server == nullptr) return EXIT_FAILURE; auto defer_free = ::absl::MakeCleanup([&]() { delete fuse_server; }); // init fuse - if (fuse_server->Init(argc, argv, &mount_option) == 1) return EXIT_FAILURE; + if (fuse_server->Init(argv[0], &mount_option) == 1) return EXIT_FAILURE; auto defer_uninit = ::absl::MakeCleanup([&]() { UnInitFuseClient(); }); // init global log - InitLog(argv[0], mount_option.conf); + InitLog(argv[0]); + + // print current gflags + LOG(INFO) << dingofs::GenCurrentFlags(); // create fuse session if (fuse_server->CreateSession() == 1) return EXIT_FAILURE; @@ -83,21 +128,11 @@ int main(int argc, char* argv[]) { // init fuse client if (InitFuseClient(argv[0], &mount_option) != 0) { - LOG(ERROR) << "init fuse client fail, conf=" << mount_option.conf; + LOG(ERROR) << "init fuse client fail"; return EXIT_FAILURE; } - // init config - Configuration conf; - conf.SetConfigPath(mount_option.conf); - if (!conf.LoadConfig()) { - LOG(ERROR) << "load config file fail: " << mount_option.conf; - } - - dingofs::client::UdsOption uds_option; - dingofs::client::InitUdsOption(&conf, &uds_option); - - if (fuse_server->Serve(uds_option.fd_comm_path) == 1) return EXIT_FAILURE; + if (fuse_server->Serve() == 1) return EXIT_FAILURE; return EXIT_SUCCESS; } diff --git a/src/client/vfs/hub/vfs_hub.cc b/src/client/vfs/hub/vfs_hub.cc index 7487b921b..94a5b3dad 100644 --- a/src/client/vfs/hub/vfs_hub.cc +++ b/src/client/vfs/hub/vfs_hub.cc @@ -37,7 +37,6 @@ #include "common/blockaccess/rados/rados_common.h" #include "common/options/cache.h" #include "common/options/client.h" -#include "common/options/trace.h" #include "common/status.h" #include "common/trace/log_trace_exporter.h" #include "common/trace/noop_tracer.h" @@ -45,7 +44,6 @@ #include "fmt/format.h" #include "gflags/gflags.h" #include "glog/logging.h" -#include "utils/configuration.h" #include "utils/executor/thread/executor_impl.h" namespace dingofs { @@ -62,13 +60,6 @@ Status VFSHubImpl::Start(const VFSConfig& vfs_conf, vfs_option_ = vfs_option; - utils::Configuration conf; - conf.SetConfigPath(vfs_conf.config_path); - if (!conf.LoadConfig()) { - LOG(ERROR) << "load config fail, confPath = " << vfs_conf.config_path; - return Status::Internal("load config fail"); - } - MetaSystemUPtr rela_meta_system; if (vfs_conf.fs_type == "vfs_memory") { rela_meta_system = std::make_unique(); @@ -77,13 +68,11 @@ Status VFSHubImpl::Start(const VFSConfig& vfs_conf, rela_meta_system = std::make_unique(); } else if (vfs_conf.fs_type == "vfs_v2" || vfs_conf.fs_type == "vfs_mds") { - std::string mds_addrs; - conf.GetValueFatalIfFail("mds.addr", &mds_addrs); - LOG(INFO) << fmt::format("mds addr: {}.", mds_addrs); + LOG(INFO) << fmt::format("mds addr: {}.", vfs_conf.mds_addrs); - rela_meta_system = v2::MDSMetaSystem::Build(vfs_conf.fs_name, mds_addrs, - vfs_conf.mount_point, - vfs_option.dummy_server_port); + rela_meta_system = v2::MDSMetaSystem::Build( + vfs_conf.fs_name, vfs_conf.mds_addrs, vfs_conf.mount_point, + vfs_option.dummy_server_port); } else { return Status::Internal("not unknown file system"); } diff --git a/src/client/vfs/hub/vfs_hub.h b/src/client/vfs/hub/vfs_hub.h index 1c59f778d..923d28144 100644 --- a/src/client/vfs/hub/vfs_hub.h +++ b/src/client/vfs/hub/vfs_hub.h @@ -35,7 +35,6 @@ #include "client/vfs/vfs.h" #include "client/vfs/vfs_meta.h" #include "common/blockaccess/block_accesser.h" -#include "common/options/client.h" #include "common/status.h" #include "common/trace/itracer.h" #include "utils/executor/executor.h" diff --git a/src/client/vfs/vfs.h b/src/client/vfs/vfs.h index f4c379b9d..8114f49ba 100644 --- a/src/client/vfs/vfs.h +++ b/src/client/vfs/vfs.h @@ -22,9 +22,9 @@ #include #include +#include "client/common/client_option.h" #include "client/vfs/data_buffer.h" #include "client/vfs/vfs_meta.h" -#include "common/options/client.h" #include "common/status.h" #include "common/trace/context.h" #include "common/trace/itracer.h" @@ -34,9 +34,9 @@ namespace client { namespace vfs { struct VFSConfig { + std::string mds_addrs; std::string mount_point; std::string fs_name; - std::string config_path; std::string fs_type; // vfs_mds/vfs_memory/vfs_local }; diff --git a/src/client/vfs/vfs_impl.cc b/src/client/vfs/vfs_impl.cc index 5246069fe..d0109b588 100644 --- a/src/client/vfs/vfs_impl.cc +++ b/src/client/vfs/vfs_impl.cc @@ -42,7 +42,6 @@ #include "fmt/format.h" #include "glog/logging.h" #include "linux/fs.h" -#include "utils/configuration.h" #include "utils/encode.h" #include "utils/net_common.h" #include "vfs_meta.h" diff --git a/src/client/vfs/vfs_wrapper.cc b/src/client/vfs/vfs_wrapper.cc index 87cf78691..0f68c295e 100644 --- a/src/client/vfs/vfs_wrapper.cc +++ b/src/client/vfs/vfs_wrapper.cc @@ -37,12 +37,10 @@ #include "client/vfs/vfs_meta.h" #include "common/blockaccess/block_access_log.h" #include "common/define.h" -#include "common/io_buffer.h" #include "common/metrics/client/client.h" #include "common/metrics/metric_guard.h" #include "common/options/client.h" #include "common/status.h" -#include "utils/configuration.h" namespace dingofs { namespace client { @@ -63,17 +61,6 @@ static auto& g_rw_metric = VFSRWMetric::GetInstance(); ClientOpMetricGuard clientOpMetricGuard( \ &rc, {&client_op_metric_->op##REQUEST, &client_op_metric_->opAll}); -static Status LoadConfig(const std::string& config_path, - utils::Configuration& conf) { - conf.SetConfigPath(config_path); - if (!conf.LoadConfig()) { - return Status::InvalidParam("load config fail"); - } - conf.PrintConfig(); - - return Status::OK(); -} - static Status InitLog() { bool succ = dingofs::client::InitAccessLog(FLAGS_log_dir) && dingofs::cache::InitCacheTraceLog(FLAGS_log_dir) && @@ -101,18 +88,12 @@ Status VFSWrapper::Start(const char* argv0, const VFSConfig& vfs_conf) { AccessLogGuard log( [&]() { return absl::StrFormat("start: %s", s.ToString()); }); - // load config - s = LoadConfig(vfs_conf.config_path, conf_); - if (!s.ok()) { - return s; - } - // init client option VFSOption vfs_option; if (vfs_conf.fs_type == "vfs" || vfs_conf.fs_type == "vfs_v2" || vfs_conf.fs_type == "vfs_mds" || vfs_conf.fs_type == "vfs_local" || vfs_conf.fs_type == "vfs_memory") { - InitVFSOption(&conf_, &vfs_option); + InitVFSOption(&vfs_option); DINGOFS_RETURN_NOT_OK(InitLog()); } else { diff --git a/src/client/vfs/vfs_wrapper.h b/src/client/vfs/vfs_wrapper.h index b573f9b4f..a8789b5e3 100644 --- a/src/client/vfs/vfs_wrapper.h +++ b/src/client/vfs/vfs_wrapper.h @@ -24,7 +24,6 @@ #include "client/vfs/data_buffer.h" #include "client/vfs/vfs.h" #include "common/metrics/client/client.h" -#include "common/options/client.h" namespace dingofs { namespace client { @@ -132,8 +131,6 @@ class VFSWrapper { bool Dump(); bool Load(); - utils::Configuration conf_; - std::unique_ptr vfs_; std::unique_ptr client_op_metric_; }; diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 6450c8553..1d763d211 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(dingofs_common rpc_stream.cc io_buffer.cc version.cc + flag.cc ) target_link_libraries(dingofs_common dingofs_utils diff --git a/src/common/blockaccess/accesser.h b/src/common/blockaccess/accesser.h index 79122ffed..cb6c6a51a 100644 --- a/src/common/blockaccess/accesser.h +++ b/src/common/blockaccess/accesser.h @@ -18,6 +18,7 @@ #define DINGOFS_COMMON_BLOCK_ACCESS_DATA_ACCESSER_H_ #include +#include #include #include diff --git a/src/common/blockaccess/accesser_common.h b/src/common/blockaccess/accesser_common.h index d2188cf85..e97f42ef2 100644 --- a/src/common/blockaccess/accesser_common.h +++ b/src/common/blockaccess/accesser_common.h @@ -24,6 +24,7 @@ #include "common/blockaccess/rados/rados_common.h" #include "common/blockaccess/s3/s3_common.h" +#include "common/options/blockaccess.h" #include "common/status.h" namespace dingofs { @@ -40,25 +41,14 @@ struct BlockAccesserThrottleOptions { }; inline void InitBlockAccesserThrottleOptions( - utils::Configuration* conf, BlockAccesserThrottleOptions* options) { - LOG_IF(FATAL, !conf->GetUInt64Value("s3.throttle.iopsTotalLimit", - &options->iopsTotalLimit)); - LOG_IF(FATAL, !conf->GetUInt64Value("s3.throttle.iopsReadLimit", - &options->iopsReadLimit)); - LOG_IF(FATAL, !conf->GetUInt64Value("s3.throttle.iopsWriteLimit", - &options->iopsWriteLimit)); - LOG_IF(FATAL, - !conf->GetUInt64Value("s3.throttle.bpsTotalMB", &options->bpsTotalMB)); - LOG_IF(FATAL, - !conf->GetUInt64Value("s3.throttle.bpsReadMB", &options->bpsReadMB)); - LOG_IF(FATAL, - !conf->GetUInt64Value("s3.throttle.bpsWriteMB", &options->bpsWriteMB)); - - if (!conf->GetUInt64Value("s3.maxAsyncRequestInflightBytes", - &options->maxAsyncRequestInflightBytes)) { - LOG(WARNING) << "Not found s3.maxAsyncRequestInflightBytes in conf"; - options->maxAsyncRequestInflightBytes = 0; - } + BlockAccesserThrottleOptions* options) { + options->iopsTotalLimit = FLAGS_iops_total_limit; + options->iopsReadLimit = FLAGS_iops_read_limit; + options->iopsWriteLimit = FLAGS_iops_write_limit; + options->bpsTotalMB = FLAGS_io_bandwidth_total_mb; + options->bpsReadMB = FLAGS_io_bandwidth_read_mb; + options->bpsWriteMB = FLAGS_io_bandwidth_write_mb; + options->maxAsyncRequestInflightBytes = FLAGS_io_max_inflight_async_bytes; } enum AccesserType : uint8_t { diff --git a/src/common/blockaccess/s3/aws/aws_s3_common.h b/src/common/blockaccess/s3/aws/aws_s3_common.h index f04ee0e46..ad707a738 100644 --- a/src/common/blockaccess/s3/aws/aws_s3_common.h +++ b/src/common/blockaccess/s3/aws/aws_s3_common.h @@ -25,7 +25,6 @@ #include "aws/core/utils/memory/stl/AWSStreamFwd.h" #include "aws/core/utils/stream/PreallocatedStreamBuf.h" #include "common/blockaccess/accesser_common.h" -#include "utils/configuration.h" #include "utils/macros.h" #define AWS_ALLOCATE_TAG __FILE__ ":" STRINGIFY(__LINE__) diff --git a/src/common/blockaccess/s3/s3_common.h b/src/common/blockaccess/s3/s3_common.h index e476d5fc2..61c94f35c 100644 --- a/src/common/blockaccess/s3/s3_common.h +++ b/src/common/blockaccess/s3/s3_common.h @@ -17,14 +17,17 @@ #ifndef DINGOFS_BLOCK_ACCESS_S3_COMMON_H_ #define DINGOFS_BLOCK_ACCESS_S3_COMMON_H_ +#include +#include + #include +#include "common/options/blockaccess.h" #include "fmt/format.h" -#include "utils/configuration.h" +#include "glog/logging.h" namespace dingofs { namespace blockaccess { - struct S3Info { // should get from mds std::string ak; @@ -58,61 +61,47 @@ struct S3Options { AwsSdkConfig aws_sdk_config; }; -inline void InitAwsSdkConfig(utils::Configuration* conf, - AwsSdkConfig* aws_sdk_config) { - LOG_IF(FATAL, !conf->GetIntValue("s3.logLevel", &aws_sdk_config->loglevel)); - if (!conf->GetStringValue("client.common.logDir", - &aws_sdk_config->log_prefix)) { - LOG(INFO) << fmt::format( - "Not found client.common.logDir in conf, use default {}", - aws_sdk_config->log_prefix); +inline void InitAwsSdkConfig(AwsSdkConfig* aws_sdk_config) { + aws_sdk_config->region = FLAGS_s3_region; + aws_sdk_config->loglevel = FLAGS_s3_loglevel; + + aws_sdk_config->log_prefix = FLAGS_s3_log_prefix; + gflags::CommandLineFlagInfo flag; + gflags::GetCommandLineFlagInfo("s3_log_prefix", &flag); + if (flag.is_default) { + LOG(INFO) << fmt::format("s3_log_prefix use default value {}", + aws_sdk_config->log_prefix); } else { aws_sdk_config->log_prefix = fmt::format("{}/aws_sdk_{}_", aws_sdk_config->log_prefix, getpid()); + LOG(INFO) << fmt::format("s3_log_prefix: {}", aws_sdk_config->log_prefix); } - LOG_IF(FATAL, - !conf->GetBoolValue("s3.verify_SSL", &aws_sdk_config->verify_ssl)); - LOG_IF(FATAL, !conf->GetIntValue("s3.maxConnections", - &aws_sdk_config->max_connections)); - LOG_IF(FATAL, !conf->GetIntValue("s3.connectTimeout", - &aws_sdk_config->connect_timeout)); - LOG_IF(FATAL, !conf->GetIntValue("s3.requestTimeout", - &aws_sdk_config->request_timeout)); - - if (!conf->GetBoolValue("s3.use_crt_client", - &aws_sdk_config->use_crt_client)) { - aws_sdk_config->use_crt_client = true; - LOG(INFO) << fmt::format( - "Not found s3.use_crt_client in conf, use default {}", - aws_sdk_config->use_crt_client); - } + aws_sdk_config->verify_ssl = FLAGS_s3_verify_ssl; + aws_sdk_config->max_connections = FLAGS_s3_max_connections; + aws_sdk_config->connect_timeout = FLAGS_s3_connect_timeout; + aws_sdk_config->request_timeout = FLAGS_s3_request_timeout; - if (!conf->GetBoolValue("s3.use_thread_pool", - &aws_sdk_config->use_thread_pool)) { - aws_sdk_config->use_thread_pool = true; - LOG(INFO) << fmt::format( - "Not found s3.use_thread_pool in conf, use default {}", - aws_sdk_config->use_thread_pool); + aws_sdk_config->use_crt_client = FLAGS_s3_use_crt_client; + if (aws_sdk_config->use_crt_client) { + LOG(INFO) << "s3 use crt client."; } - - if (!conf->GetIntValue("s3.async_thread_num_in_thread_pool", - &aws_sdk_config->async_thread_num)) { - aws_sdk_config->async_thread_num = 16; - LOG(INFO) << fmt::format( - "Not found s3.async_thread_num_in_thread_pool in conf, use default {}", - aws_sdk_config->async_thread_num); + aws_sdk_config->use_thread_pool = FLAGS_s3_use_thread_pool; + if (aws_sdk_config->use_thread_pool) { + LOG(INFO) << "s3 use thread pool."; } - LOG_IF(FATAL, !conf->GetBoolValue("s3.useVirtualAddressing", - &aws_sdk_config->use_virtual_addressing)); - LOG_IF(FATAL, !conf->GetStringValue("s3.region", &aws_sdk_config->region)); + aws_sdk_config->async_thread_num = FLAGS_s3_async_thread_num; + LOG(INFO) << fmt::format("s3 async thread num in thread pool: {}.", + aws_sdk_config->async_thread_num); - if (!conf->GetBoolValue("s3.enableTelemetry", - &aws_sdk_config->enable_telemetry)) { - aws_sdk_config->enable_telemetry = false; - LOG(WARNING) << "Not found s3.enableTelemetry in conf, default false."; - } + aws_sdk_config->use_virtual_addressing = FLAGS_s3_use_virtual_address; + LOG(INFO) << fmt::format("s3 use virtual addressing: {}.", + aws_sdk_config->use_virtual_addressing); + + aws_sdk_config->enable_telemetry = FLAGS_s3_enable_telemetry; + LOG(INFO) << fmt::format("s3 enable telemetry: {}.", + aws_sdk_config->enable_telemetry); } } // namespace blockaccess diff --git a/src/common/flag.cc b/src/common/flag.cc new file mode 100644 index 000000000..214c6c7c3 --- /dev/null +++ b/src/common/flag.cc @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2024 dingodb.com, Inc. All Rights Reserved + * + * 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: DingoFS + * Created Date: 2025-08-07 + * Author: Jingli Chen (Wine93) + */ + +#include "common/flag.h" + +#include +#include + +#include +#include +#include + +#include "cache/utils/helper.h" +#include "utils/string.h" + +namespace dingofs { + +FlagsInfo FlagsHelper::Parse(int* argc, char*** argv, + const FlagExtraInfo& extra_info) { + FlagsInfo flags; + for (int i = 1; i < *argc; i++) { + if (strcmp((*argv)[i], "-v") == 0 || strcmp((*argv)[i], "--version") == 0) { + flags.show_version = true; + } else if (strcmp((*argv)[i], "-h") == 0 || + strcmp((*argv)[i], "--help") == 0) { + flags.show_help = true; + } else if (strcmp((*argv)[i], "-t") == 0 || + strcmp((*argv)[i], "--tmpl") == 0) { + flags.create_template = true; + } + } + + if (!flags.show_help && !flags.show_version && !flags.create_template) { + gflags::ParseCommandLineNonHelpFlags(argc, argv, true); + } + flags.gflags = GetAllGFlags(extra_info.patterns); + flags.extra_info = extra_info; + return flags; +} + +std::string FlagsHelper::GenHelp(const FlagsInfo& flags) { + auto rows = Normalize(flags); + size_t max_name_length = 0; + std::for_each(rows.begin(), rows.end(), [&](const Row& row) { + max_name_length = std::max(max_name_length, row.name.size()); + }); + + std::ostringstream os; + // print program name and version + os << flags.extra_info.program << " " << dingofs::Version() << "\n\n"; + os << "Usage:\n"; + os << flags.extra_info.usage << "\n"; + os << "\n"; + os << "Options:\n"; + for (const auto& row : rows) { + os << " --" << std::left << std::setw(max_name_length) << row.name + << std::right << " " << row.description << " " << row.default_value + << "\n"; + } + + os << "\n"; + os << "Examples:\n"; + os << flags.extra_info.examples << "\n"; + + os << "\n"; + os << flags.extra_info.program + << " was written by dingofs team "; + return os.str(); +} + +std::string FlagsHelper::GenTemplate(const FlagsInfo& flags) { + std::ostringstream os; + for (const auto& gflag : flags.gflags) { + auto key = gflag.name; + auto value = gflag.default_value; + if (key == "id") { + value = utils::GenUuid(); + } + os << "--" << key << "=" << value << "\n"; + } + return os.str(); +} + +std::string FlagsHelper::GenCurrentFlags(const FlagsInfo& flags) { + std::ostringstream os; + os << "Current flags:\n"; + for (const auto& gflag : flags.gflags) { + os << " --" << gflag.name << "=" << gflag.current_value << "\n"; + } + return os.str(); +} + +std::vector FlagsHelper::GetAllGFlags( + const std::vector& patterns) { + std::vector all_flags; + std::vector flags_out; + + gflags::GetAllFlags(&all_flags); + for (const auto& flag : all_flags) { + if (flag.description.empty()) { // hiden the flag + continue; + } + + for (const auto& pattern : patterns) { + if (flag.filename.find(pattern) != std::string::npos) { + flags_out.push_back(flag); + break; + } + } + } + + std::sort(flags_out.begin(), flags_out.end(), + [](const auto& a, const auto& b) { return a.name < b.name; }); + return flags_out; +} + +std::vector FlagsHelper::Normalize(const FlagsInfo& flags) { + Row row; + std::vector rows; + for (const auto& gflag : flags.gflags) { + row.name = gflag.name + "=" + gflag.type; + row.description = gflag.description; + + if (gflag.default_value.empty() && gflag.has_validator_fn) { + row.default_value = cache::Helper::RedString("[required]"); + } else if (!gflag.default_value.empty()) { + row.default_value = absl::StrFormat("(default: %s)", gflag.default_value); + } else { + row.default_value = ""; + } + rows.push_back(row); + } + return rows; +} + +} // namespace dingofs diff --git a/src/common/flag.h b/src/common/flag.h new file mode 100644 index 000000000..f737bdf4a --- /dev/null +++ b/src/common/flag.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 dingodb.com, Inc. All Rights Reserved + * + * 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: DingoFS + * Created Date: 2025-08-07 + * Author: Jingli Chen (Wine93) + */ + +#ifndef DINGOFS_SRC_COMMON_FLAG_H_ +#define DINGOFS_SRC_COMMON_FLAG_H_ + +#include + +#include + +#include "common/version.h" + +namespace dingofs { +struct FlagExtraInfo { + std::string program; // program name + std::string usage; // usage info + std::string examples; // examples + std::vector patterns; // used for filtering gflags +}; + +struct FlagsInfo { + bool show_help{false}; + bool show_version{false}; + bool create_template{false}; + std::vector gflags; + FlagExtraInfo extra_info; +}; + +static FlagsInfo g_flags; + +class FlagsHelper { + public: + static FlagsInfo Parse(int* argc, char*** argv, + const FlagExtraInfo& extra_info); + + static std::string GenHelp(const FlagsInfo& flags); + static std::string GenTemplate(const FlagsInfo& flags); + static std::string GenCurrentFlags(const FlagsInfo& flags); + + private: + struct Row { + std::string name; + std::string description; + std::string default_value; + }; + + static std::vector GetAllGFlags( + const std::vector& patterns); + static std::vector Normalize(const FlagsInfo& flags); +}; + +static int ParseFlags(int* argc, char*** argv, const FlagExtraInfo& extras) { + g_flags = FlagsHelper::Parse(argc, argv, extras); + if (g_flags.show_help) { + std::cout << FlagsHelper::GenHelp(g_flags) << "\n"; + return 1; + } else if (g_flags.show_version) { + std::cout << dingofs::Version() << "\n"; + return 1; + } else if (g_flags.create_template) { + std::cout << FlagsHelper::GenTemplate(g_flags); + return 1; + } + + return 0; +} + +static std::string GenCurrentFlags() { + return FlagsHelper::GenCurrentFlags(g_flags); +} + +} // namespace dingofs + +#endif // DINGOFS_SRC_COMMON_FLAG_H_ diff --git a/src/common/options/CMakeLists.txt b/src/common/options/CMakeLists.txt index 47ca64a9e..ebc8410fb 100644 --- a/src/common/options/CMakeLists.txt +++ b/src/common/options/CMakeLists.txt @@ -19,9 +19,6 @@ target_link_libraries(blockaccess_options gflags::gflags ) -add_library(trace_options - trace.cc -) target_link_libraries(blockaccess_options gflags::gflags ) @@ -30,7 +27,6 @@ add_library(client_options client.cc ) target_link_libraries(client_options - trace_options cache_lib brpc::brpc fmt::fmt diff --git a/src/common/options/blockaccess.cc b/src/common/options/blockaccess.cc index 23edffce0..66d21705b 100644 --- a/src/common/options/blockaccess.cc +++ b/src/common/options/blockaccess.cc @@ -14,14 +14,42 @@ * limitations under the License. */ -#include - #include "common/options/blockaccess.h" +#include + namespace dingofs { namespace blockaccess { +// rados option DEFINE_int32(rados_op_timeout, 120, "rados operation timeout in seconds"); +// aws option +DEFINE_string(s3_region, "us-east-1", "aws s3 region"); +DEFINE_int32(s3_loglevel, 4, "aws sdk log level"); +DEFINE_string(s3_log_prefix, "/tmp/aws_sdk_", "aws sdk log prefix"); +DEFINE_bool(s3_verify_ssl, false, "whether to verify ssl"); +DEFINE_int32(s3_max_connections, 32, "max connections to s3"); +DEFINE_int32(s3_connect_timeout, 60000, "S3 connect timeout in milliseconds"); +DEFINE_int32(s3_request_timeout, 10000, "S3 request timeout in milliseconds"); +DEFINE_bool(s3_use_crt_client, true, "whether to use crt client"); +DEFINE_bool(s3_use_thread_pool, true, "whether to use thread pool"); +DEFINE_int32(s3_async_thread_num, 16, "async thread num in thread pool"); +DEFINE_bool(s3_use_virtual_address, false, "whether to use virtual address"); +DEFINE_bool(s3_enable_telemetry, false, "whether to enable telemetry"); + +// throttle options +DEFINE_uint32(iops_total_limit, 0, "total iops limit(0 means no limit)"); +DEFINE_uint32(iops_read_limit, 0, "read iops limit(0 means no limit)"); +DEFINE_uint32(iops_write_limit, 0, "write iops limit(0 means no limit)"); +DEFINE_uint32(io_bandwidth_total_mb, 0, + "total io bandwidth limit in MB(0 means no limit)"); +DEFINE_uint32(io_bandwidth_read_mb, 0, + "read io bandwidth limit in MB(0 means no limit)"); +DEFINE_uint32(io_bandwidth_write_mb, 0, + "write io bandwidth limit in MB(0 means no limit)"); +DEFINE_uint32(io_max_inflight_async_bytes, 0, + "max inflight async bytes(0 means no limit)"); + } // namespace blockaccess } // namespace dingofs \ No newline at end of file diff --git a/src/common/options/blockaccess.h b/src/common/options/blockaccess.h index a019703ec..22eefa87b 100644 --- a/src/common/options/blockaccess.h +++ b/src/common/options/blockaccess.h @@ -24,6 +24,30 @@ namespace blockaccess { DECLARE_int32(rados_op_timeout); +// aws option +DECLARE_string(s3_region); +DECLARE_int32(s3_loglevel); +DECLARE_string(s3_log_prefix); +DECLARE_bool(s3_verify_ssl); +DECLARE_int32(s3_max_connections); +DECLARE_int32(s3_connect_timeout); +DECLARE_int32(s3_request_timeout); +DECLARE_bool(s3_use_crt_client); +DECLARE_bool(s3_use_thread_pool); +DECLARE_int32(s3_async_thread_num); +DECLARE_bool(s3_use_thread_pool); +DECLARE_bool(s3_use_virtual_address); +DECLARE_bool(s3_enable_telemetry); + +// throttle options +DECLARE_uint32(iops_total_limit); +DECLARE_uint32(iops_read_limit); +DECLARE_uint32(iops_write_limit); +DECLARE_uint32(io_bandwidth_total_mb); +DECLARE_uint32(io_bandwidth_read_mb); +DECLARE_uint32(io_bandwidth_write_mb); +DECLARE_uint32(io_max_inflight_async_bytes); + } // namespace blockaccess } // namespace dingofs #endif // DINGOFS_COMMON_OPTIONS_BLOCK_ACCESS_OPTION_H_ \ No newline at end of file diff --git a/src/common/options/client.cc b/src/common/options/client.cc index b88688930..695e5b118 100644 --- a/src/common/options/client.cc +++ b/src/common/options/client.cc @@ -18,26 +18,22 @@ #include #include - -#include "common/options/blockaccess.h" -#include "common/options/trace.h" -#include "utils/configuration.h" +#include namespace dingofs { namespace client { +DEFINE_string(client_log_dir, "/tmp", "set log directory"); -// ############## gflags ############## - -DEFINE_int32(vlog_level, 0, "set vlog level"); -DEFINE_validator(vlog_level, [](const char* /*name*/, int32_t value) { +DEFINE_int32(client_log_level, 0, "set log level"); +DEFINE_validator(client_log_level, [](const char* /*name*/, int32_t value) { FLAGS_v = value; LOG(INFO) << "current verbose logging level is `" << FLAGS_v << "`"; return true; }); -DEFINE_bool(client_data_single_thread_read, false, - "use single thread read to chunk, if true, use single thread read " - "to block cache, otherwise use executor read with async"); +DEFINE_string(fstype, "vfs_v2", + "vfs type(e.g. vfs_v2|vfs_mds|vfs_local|vfs_memory)"); + DEFINE_int32(client_bthread_worker_num, 0, "bthread worker num"); // access log @@ -47,15 +43,8 @@ DEFINE_validator(client_access_logging, brpc::PassValidate); DEFINE_int64(client_access_log_threshold_us, 0, "access log threshold"); DEFINE_validator(client_access_log_threshold_us, brpc::PassValidate); -// fuse module -DEFINE_bool(client_fuse_file_info_direct_io, false, "use direct io for file"); -DEFINE_validator(client_fuse_file_info_direct_io, brpc::PassValidate); - -DEFINE_bool(client_fuse_file_info_keep_cache, false, "keep file page cache"); -DEFINE_validator(client_fuse_file_info_keep_cache, brpc::PassValidate); - -DEFINE_bool(client_fuse_enable_readdir_cache, true, "enable readdir cache"); -DEFINE_validator(client_fuse_enable_readdir_cache, brpc::PassValidate); +DEFINE_bool(fuse_enable_readdir_cache, true, "enable readdir cache"); +DEFINE_validator(fuse_enable_readdir_cache, brpc::PassValidate); DEFINE_uint32(client_fuse_entry_cache_timeout_s, 3600, "fuse entry cache timeout in seconds"); @@ -147,7 +136,7 @@ DEFINE_int64(client_vfs_warmup_trigger_restart_interval_secs, 1800, DEFINE_validator(client_vfs_warmup_trigger_restart_interval_secs, brpc::PassValidate); -// ## vfs meta +// vfs meta DEFINE_bool(client_vfs_inode_cache_enable, true, "enable inode cache, default is false"); DEFINE_validator(client_vfs_inode_cache_enable, brpc::PassValidate); @@ -164,7 +153,7 @@ DEFINE_uint32(client_write_slicce_operation_merge_delay_us, 10, DEFINE_validator(client_write_slicce_operation_merge_delay_us, brpc::PassValidate); -// begin used in inode_blocks_service +// inode_blocks_service DEFINE_uint32(format_file_offset_width, 20, "Width of file offset in format"); DEFINE_validator(format_file_offset_width, brpc::PassValidate); @@ -190,149 +179,50 @@ DEFINE_validator(format_delimiter, return true; }); -// end used in inode_blocks_service - -// ############## gflags end ############## - -// ############## options ############## - -void InitFuseOption(utils::Configuration* c, FuseOption* option) { - { // fuse conn info - auto* o = &option->conn_info; - c->GetValueFatalIfFail("fuse.conn_info.want_splice_move", - &o->want_splice_move); - c->GetValueFatalIfFail("fuse.conn_info.want_splice_read", - &o->want_splice_read); - c->GetValueFatalIfFail("fuse.conn_info.want_splice_write", - &o->want_splice_write); - c->GetValueFatalIfFail("fuse.conn_info.want_auto_inval_data", - &o->want_auto_inval_data); - } - - { // fuse file info - c->GetValueFatalIfFail("fuse.file_info.direct_io", - &FLAGS_client_fuse_file_info_direct_io); - c->GetValueFatalIfFail("fuse.file_info.keep_cache", - &FLAGS_client_fuse_file_info_keep_cache); - } -} - -void InitVFSOption(utils::Configuration* conf, VFSOption* option) { - if (!conf->GetIntValue("block_access.rados.rados_op_timeout", - &blockaccess::FLAGS_rados_op_timeout)) { - LOG(INFO) << "Not found `block_access.rados.rados_op_timeout` in conf, " - "default to " - << blockaccess::FLAGS_rados_op_timeout; - } - - blockaccess::InitAwsSdkConfig( - conf, &option->block_access_opt.s3_options.aws_sdk_config); - blockaccess::InitBlockAccesserThrottleOptions( - conf, &option->block_access_opt.throttle_options); - - InitMemoryPageOption(conf, &option->page_option); - - InitBlockCacheOption(conf); - InitRemoteBlockCacheOption(conf); - - InitFuseOption(conf, &option->fuse_option); - InitPrefetchOption(conf); - InitWarmupOption(conf); - - // vfs data related - if (!conf->GetBoolValue("vfs.data.writeback", - &option->data_option.writeback)) { - LOG(INFO) << "Not found `vfs.data.writeback` in conf, default:" - << (option->data_option.writeback ? "true" : "false"); - } - - if (!conf->GetStringValue("vfs.data.writeback_suffix", - &option->data_option.writeback_suffix)) { - LOG(INFO) << "Not found `vfs.data.writeback_suffix` in conf, " - "default to: " - << option->data_option.writeback_suffix; - } - - if (!conf->GetIntValue("vfs.data.vfs_periodic_flush_interval_ms", - &FLAGS_client_vfs_periodic_flush_interval_ms)) { - LOG(INFO) << "Not found `vfs.data.vfs_periodic_flush_interval_ms` in conf, " - "default to " - << FLAGS_client_vfs_periodic_flush_interval_ms; - } - - if (!conf->GetIntValue("vfs.data.flush_bg_thread", - &FLAGS_client_vfs_flush_bg_thread)) { - LOG(INFO) << "Not found `vfs.data.flush_bg_thread` in conf, " - "default to " - << FLAGS_client_vfs_flush_bg_thread; - } - - if (!conf->GetBoolValue("vfs.data.single_tread_read", - &FLAGS_client_data_single_thread_read)) { - LOG(INFO) << "Not found `vfs.data.single_tread_read` in conf, " - "default to " - << (FLAGS_client_data_single_thread_read ? "true" : "false"); - } - - if (!conf->GetIntValue("vfs.data.read_executor_thread", - &FLAGS_client_vfs_read_executor_thread)) { - LOG(INFO) << "Not found `vfs.data.read_executor_thread` in conf, " - "default to " - << FLAGS_client_vfs_read_executor_thread; - } - - // vfs meta related - if (!conf->GetUInt32Value("vfs.meta.max_name_length", - &option->meta_option.max_name_length)) { - LOG(INFO) << "Not found `vfs.meta.max_name_length` in conf, default to " - << option->meta_option.max_name_length; - } - - if (!conf->GetUInt32Value("vfs.dummy_server.port", - &option->dummy_server_port)) { - LOG(INFO) << "Not found `vfs.dummy_server.port` in conf, default to " - << option->dummy_server_port; - } - - if (!conf->GetIntValue("vfs.bthread_worker_num", - &FLAGS_client_bthread_worker_num)) { - FLAGS_client_bthread_worker_num = 0; - LOG(INFO) << "Not found `vfs.bthread_worker_num` in conf, " - "default to 0"; - } - - if (!conf->GetBoolValue("vfs.access_logging", &FLAGS_client_access_logging)) { - LOG(INFO) << "Not found `vfs.access_logging` in conf, default: " - << FLAGS_client_access_logging; - } - if (!conf->GetInt64Value("vfs.access_log_threshold_us", - &FLAGS_client_access_log_threshold_us)) { - LOG(INFO) << "Not found `vfs.access_log_threshold_us` in conf, " - "default: " - << FLAGS_client_access_log_threshold_us; - } - - if (!conf->GetBoolValue("vfs.vfs_meta_logging", - &FLAGS_client_vfs_meta_logging)) { - LOG(INFO) << "Not found `vfs.vfs_meta_logging` in conf, default: " - << FLAGS_client_vfs_meta_logging; - } - if (!conf->GetInt64Value("vfs.vfs_meta_log_threshold_u", - &FLAGS_client_vfs_meta_log_threshold_us)) { - LOG(INFO) << "Not found `vfs.vfs_meta_log_threshold_u` in conf, " - "default: " - << FLAGS_client_vfs_meta_log_threshold_us; - } - - if (!conf->GetBoolValue("vfs.trace_logging", &FLAGS_trace_logging)) { - LOG(INFO) << "Not found `vfs.trace_logging` in conf, default: " - << FLAGS_trace_logging; - } - - SetBrpcOpt(conf); -} - -// ############## options end ############## +// fuse module +DEFINE_bool(fuse_file_info_direct_io, false, "use direct io for file"); +DEFINE_validator(fuse_file_info_direct_io, brpc::PassValidate); +DEFINE_bool(fuse_file_info_keep_cache, true, "keep file page cache"); +DEFINE_validator(fuse_file_info_keep_cache, brpc::PassValidate); +DEFINE_bool(fuse_conn_info_want_splice_move, false, + "the fuse device try to move pages instead of copying them"); +DEFINE_validator(fuse_conn_info_want_splice_move, brpc::PassValidate); +DEFINE_bool(fuse_conn_info_want_splice_read, false, + "use splice when reading from the fuse device"); +DEFINE_validator(fuse_conn_info_want_splice_read, brpc::PassValidate); +DEFINE_bool(fuse_conn_info_want_splice_write, false, + "use splice when writing to the fuse device"); +DEFINE_validator(fuse_conn_info_want_splice_write, brpc::PassValidate); +DEFINE_bool(fuse_conn_info_want_auto_inval_data, true, + "fuse will check the validity of the attributes on every read"); +DEFINE_validator(fuse_conn_info_want_auto_inval_data, brpc::PassValidate); + +// memory page allocator +DEFINE_uint32(data_stream_page_size, 65536, "memory page size for datastream"); +DEFINE_validator(data_stream_page_size, brpc::PassValidate); +DEFINE_uint64(data_stream_page_total_size_mb, 1024, + "total memory size for data stream"); +DEFINE_validator(data_stream_page_total_size_mb, brpc::PassValidate); +DEFINE_bool(data_stream_page_use_pool, true, + "whether to use memory pool for data stream"); +DEFINE_validator(data_stream_page_use_pool, brpc::PassValidate); + +// vfs meta +DEFINE_uint32(vfs_meta_max_name_length, 255, "max file name length"); +DEFINE_validator(vfs_meta_max_name_length, brpc::PassValidate); + +// vfs data +DEFINE_bool(vfs_data_writeback, false, "whether to use writeback"); +DEFINE_validator(vfs_data_writeback, brpc::PassValidate); +DEFINE_string(vfs_data_writeback_suffix, "", + "file name with suffix for writeback"); + +DEFINE_uint32(vfs_dummy_server_port, 10000, "dummy server port"); +DEFINE_validator(vfs_dummy_server_port, brpc::PassValidate); + +// trace log +DEFINE_bool(trace_logging, false, "enable trace log"); +DEFINE_validator(trace_logging, &brpc::PassValidate); } // namespace client } // namespace dingofs diff --git a/src/common/options/client.h b/src/common/options/client.h index 03005e627..2f3274b37 100644 --- a/src/common/options/client.h +++ b/src/common/options/client.h @@ -14,27 +14,12 @@ * limitations under the License. */ -#ifndef DINGOFS_SRC_COMMON_OPTIONS_CLIENT_H_ -#define DINGOFS_SRC_COMMON_OPTIONS_CLIENT_H_ - -#ifndef DINGOFS_SRC_COMMON_OPTIONS_CLIENT_CLIENT_H_ -#define DINGOFS_SRC_COMMON_OPTIONS_CLIENT_CLIENT_H_ - -#ifndef DINGOFS_SRC_OPTIONS_CLIENT_OPTION_H_ -#define DINGOFS_SRC_OPTIONS_CLIENT_OPTION_H_ +#ifndef DINGOFS_COMMON_OPTIONS_CLIENT_OPTION_H_ +#define DINGOFS_COMMON_OPTIONS_CLIENT_OPTION_H_ #include -#include "common/blockaccess/accesser_common.h" -#include "common/const.h" -#include "common/options/cache.h" -#include "utils/configuration.h" -#include "utils/gflags_helper.h" - namespace brpc { - -DECLARE_int32(defer_close_second); -DECLARE_int32(health_check_interval); DECLARE_int32(connect_timeout_as_unreachable); DECLARE_int32(max_connection_pool_size); @@ -45,8 +30,6 @@ namespace client { #define USING_FLAG(name) using ::dingofs::client::FLAGS_##name; -// ############## gflags ############## - /** * use vlog_level to set vlog level on the fly * When vlog_level is set, CheckVLogLevel is called to check the validity of the @@ -55,19 +38,33 @@ namespace client { * You can modify the vlog level to 0 using: * curl -s http://127.0.0.1:9000/flags/vlog_level?setvalue=0 */ -DECLARE_int32(vlog_level); +// log +DECLARE_string(client_log_dir); +DECLARE_int32(client_log_level); -DECLARE_bool(client_data_single_thread_read); -DECLARE_int32(client_bthread_worker_num); +// file system +DECLARE_string(fstype); +// bthread +DECLARE_int32(client_bthread_worker_num); // access log DECLARE_bool(client_access_logging); DECLARE_int64(client_access_log_threshold_us); +// fuse mount option +DECLARE_string(fuse_mount_options); +DECLARE_bool(fuse_use_single_thread); +DECLARE_bool(fuse_use_clone_fd); +DECLARE_uint32(fuse_max_threads); + // fuse module -DECLARE_bool(client_fuse_file_info_direct_io); -DECLARE_bool(client_fuse_file_info_keep_cache); -DECLARE_bool(client_fuse_enable_readdir_cache); +DECLARE_bool(fuse_file_info_direct_io); +DECLARE_bool(fuse_file_info_keep_cache); +DECLARE_bool(fuse_enable_readdir_cache); +DECLARE_bool(fuse_conn_info_want_splice_move); +DECLARE_bool(fuse_conn_info_want_splice_read); +DECLARE_bool(fuse_conn_info_want_splice_write); +DECLARE_bool(fuse_conn_info_want_auto_inval_data); DECLARE_uint32(client_fuse_entry_cache_timeout_s); DECLARE_uint32(client_fuse_attr_cache_timeout_s); @@ -124,209 +121,24 @@ DECLARE_uint32(format_block_len_width); DECLARE_string(format_delimiter); // end used in inode_blocks_service -// ############## gflags end ############## - -// ############## options ############## - -struct UdsOption { - std::string fd_comm_path; -}; - -static void SetBrpcOpt(utils::Configuration* conf) { - dingofs::utils::GflagsLoadValueFromConfIfCmdNotSet dummy; - dummy.Load(conf, "defer_close_second", "rpc.defer.close.second", - &brpc::FLAGS_defer_close_second); - dummy.Load(conf, "health_check_interval", "rpc.healthCheckIntervalSec", - &brpc::FLAGS_health_check_interval); -} - -static void InitUdsOption(utils::Configuration* conf, UdsOption* uds_opt) { - if (!conf->GetValue("uds.fdCommPath", &uds_opt->fd_comm_path)) { - uds_opt->fd_comm_path = "/var/run"; - } -} - -static void InitPrefetchOption(utils::Configuration* c) { - c->GetValue("vfs.prefetch.blocks", &FLAGS_client_vfs_prefetch_blocks); - c->GetValue("vfs.prefetch.threads", &FLAGS_client_vfs_prefetch_threads); - c->GetValue("vfs.data.warmup.intime_warmup_enbale", - &FLAGS_client_vfs_intime_warmup_enable); -} - -static void InitWarmupOption(utils::Configuration* c) { - c->GetValue("vfs.warmup.threads", &FLAGS_client_vfs_warmup_threads); - c->GetValue("vfs.intime_warmup.enbale", - &FLAGS_client_vfs_intime_warmup_enable); - c->GetValue("vfs.intime_warmup.restart_mtime_interval_secs", - &FLAGS_client_vfs_warmup_mtime_restart_interval_secs); - c->GetValue("vfs.intime_warmup.restart_trigger_interval_secs", - &FLAGS_client_vfs_warmup_trigger_restart_interval_secs); -} - -static void InitBlockCacheOption(utils::Configuration* c) { - { // block cache option - c->GetValue("block_cache.cache_store", &cache::FLAGS_cache_store); - c->GetValue("block_cache.enable_stage", &cache::FLAGS_enable_stage); - c->GetValue("block_cache.enable_cache", &cache::FLAGS_enable_cache); - c->GetValue("block_cache.trace_logging", &cache::FLAGS_cache_trace_logging); - c->GetValue("block_cache.upload_stage_throttle_enable", - &cache::FLAGS_upload_stage_throttle_enable); - c->GetValue("block_cache.upload_stage_throttle_bandwidth_mb", - &cache::FLAGS_upload_stage_throttle_bandwidth_mb); - c->GetValue("block_cache.upload_stage_throttle_iops", - &cache::FLAGS_upload_stage_throttle_iops); - c->GetValue("block_cache.upload_stage_max_inflights", - &cache::FLAGS_upload_stage_max_inflights); - c->GetValue("block_cache.prefetch_max_inflights", - &cache::FLAGS_prefetch_max_inflights); - c->GetValue("block_cache.storage_upload_retry_timeout_s", - &cache::FLAGS_storage_upload_retry_timeout_s); - c->GetValue("block_cache.storage_download_retry_timeout_s", - &cache::FLAGS_storage_download_retry_timeout_s); - } - - { // disk cache option - c->GetValue("disk_cache.cache_dir", &cache::FLAGS_cache_dir); - c->GetValue("disk_cache.cache_size_mb", &cache::FLAGS_cache_size_mb); - c->GetValue("disk_cache.free_space_ratio", &cache::FLAGS_free_space_ratio); - c->GetValue("disk_cache.cache_expire_s", &cache::FLAGS_cache_expire_s); - c->GetValue("disk_cache.cleanup_expire_interval_ms", - &cache::FLAGS_cleanup_expire_interval_ms); - c->GetValue("disk_cache.ioring_iodepth", &cache::FLAGS_ioring_iodepth); - } - - { // disk state option - c->GetValue("disk_state.tick_duration_s", - &cache::FLAGS_disk_state_tick_duration_s); - c->GetValue("disk_state.normal2unstable_error_num", - &cache::FLAGS_disk_state_normal2unstable_error_num); - c->GetValue("disk_state.unstable2normal_succ_num", - &cache::FLAGS_disk_state_unstable2normal_succ_num); - c->GetValue("disk_state.unstable2down_s", - &cache::FLAGS_disk_state_unstable2down_s); - c->GetValue("disk_state.check_duration_ms", - &cache::FLAGS_disk_state_check_duration_ms); - } -} - -static void InitRemoteBlockCacheOption(utils::Configuration* c) { - c->GetValue("remote_cache.cache_group", &cache::FLAGS_cache_group); - c->GetValue("remote_cache.mds_addrs", &cache::FLAGS_mds_addrs); - c->GetValue("remote_cache.mds_rpc_timeout_ms", - &cache::FLAGS_mds_rpc_timeout_ms); - c->GetValue("remote_cache.mds_rpc_retry_times", - &cache::FLAGS_mds_rpc_retry_times); - c->GetValue("remote_cache.mds_request_retry_times", - &cache::FLAGS_mds_request_retry_times); - c->GetValue("remote_cache.load_members_interval_ms", - &cache::FLAGS_load_members_interval_ms); - - c->GetValue("remote_cache.fill_group_cache", &cache::FLAGS_fill_group_cache); - c->GetValue("remote_cache.subrequest_range_size", - &cache::FLAGS_subrequest_range_size); - c->GetValue("remote_cache.rpc_connect_timeout_ms", - &cache::FLAGS_rpc_connect_timeout_ms); - c->GetValue("remote_cache.rpc_connect_timeout_as_unreachable", - &brpc::FLAGS_connect_timeout_as_unreachable); - c->GetValue("remote_cache.rpc_max_connection_pool_size", - &brpc::FLAGS_max_connection_pool_size); - c->GetValue("remote_cache.put_rpc_timeout_ms", - &cache::FLAGS_put_rpc_timeout_ms); - c->GetValue("remote_cache.range_rpc_timeout_ms", - &cache::FLAGS_range_rpc_timeout_ms); - c->GetValue("remote_cache.cache_rpc_timeout_ms", - &cache::FLAGS_cache_rpc_timeout_ms); - c->GetValue("remote_cache.prefetch_rpc_timeout_ms", - &cache::FLAGS_prefetch_rpc_timeout_ms); - c->GetValue("remote_cache.ping_rpc_timeout_ms", - &cache::FLAGS_ping_rpc_timeout_ms); - c->GetValue("remote_cache.rpc_max_retry_times", - &cache::FLAGS_rpc_max_retry_times); - c->GetValue("remote_cache.rpc_max_timeout_ms", - &cache::FLAGS_rpc_max_timeout_ms); - - c->GetValue("cache_node_state.tick_duration_s", - &cache::FLAGS_cache_node_state_tick_duration_s); - c->GetValue("cache_node_state.normal2unstable_error_num", - &cache::FLAGS_cache_node_state_normal2unstable_error_num); - c->GetValue("cache_node_state.unstable2normal_succ_num", - &cache::FLAGS_cache_node_state_unstable2normal_succ_num); - c->GetValue("cache_node_state.check_duration_ms", - &cache::FLAGS_cache_node_state_check_duration_ms); -} - -// fuse option -struct FuseConnInfo { - bool want_splice_move; - bool want_splice_read; - bool want_splice_write; - bool want_auto_inval_data; -}; - -struct FuseFileInfo { - bool keep_cache; -}; - -struct FuseOption { - FuseConnInfo conn_info; - FuseFileInfo file_info; -}; - -void InitFuseOption(utils::Configuration* c, FuseOption* option); - -// memory option -struct PageOption { - uint64_t page_size; - uint64_t total_size; - bool use_pool; -}; - -static void InitMemoryPageOption(utils::Configuration* c, PageOption* option) { - // page option - c->GetValueFatalIfFail("data_stream.page.size", &option->page_size); - c->GetValueFatalIfFail("data_stream.page.total_size_mb", &option->total_size); - c->GetValueFatalIfFail("data_stream.page.use_pool", &option->use_pool); - - if (option->page_size == 0) { - CHECK(false) << "page size must greater than 0."; - } - - option->total_size = option->total_size * kMiB; - if (option->total_size < 64 * kMiB) { - CHECK(false) << "page total size must greater than 64MB."; - } -} +// unix socket path +DECLARE_string(socket_path); // vfs option -struct VFSMetaOption { - uint32_t max_name_length{255}; // max length of file name -}; - -struct VFSDataOption { - bool writeback{false}; // whether to use writeback - std::string writeback_suffix; -}; - -struct VFSOption { - blockaccess::BlockAccessOptions block_access_opt; // from config - PageOption page_option; - FuseOption fuse_option; - - VFSMetaOption meta_option; - VFSDataOption data_option; +DECLARE_uint32(vfs_meta_max_name_length); +DECLARE_bool(vfs_data_writeback); +DECLARE_string(vfs_data_writeback_suffix); +DECLARE_uint32(vfs_dummy_server_port); - uint32_t dummy_server_port{10000}; -}; - -void InitVFSOption(utils::Configuration* conf, VFSOption* option); +// memory option +DECLARE_uint32(data_stream_page_size); +DECLARE_uint64(data_stream_page_total_size_mb); +DECLARE_bool(data_stream_page_use_pool); -// ############## options end ############## +// trace log +DECLARE_bool(trace_logging); } // namespace client } // namespace dingofs -#endif // DINGOFS_COMMON_OPTIONS_CLIENT_OPTION_H_ - -#endif // DINGOFS_SRC_COMMON_OPTIONS_CLIENT_CLIENT_H_ - -#endif // DINGOFS_SRC_COMMON_OPTIONS_CLIENT_H_ +#endif // DINGOFS_COMMON_OPTIONS_CLIENT_OPTION_H_ \ No newline at end of file diff --git a/src/common/options/trace.cc b/src/common/options/trace.cc deleted file mode 100644 index be0370bd6..000000000 --- a/src/common/options/trace.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2025 dingodb.com, Inc. All Rights Reserved - * - * 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. - */ - -#include "common/options/trace.h" - -#include - -namespace dingofs { - -// trace log -DEFINE_bool(trace_logging, false, "enable trace log"); -DEFINE_validator(trace_logging, &brpc::PassValidate); - -} // namespace dingofs \ No newline at end of file diff --git a/src/common/options/trace.h b/src/common/options/trace.h deleted file mode 100644 index cdb7d7034..000000000 --- a/src/common/options/trace.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2025 dingodb.com, Inc. All Rights Reserved - * - * 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. - */ - -#ifndef DINGOFS_COMMON_OPTIONS_TRACE_DYNAMIC_OPTION_H_ -#define DINGOFS_COMMON_OPTIONS_TRACE_DYNAMIC_OPTION_H_ - -#include - -namespace dingofs { - -DECLARE_bool(trace_logging); - -} // namespace dingofs - -#endif // DINGOFS_COMMON_OPTIONS_TRACE_DYNAMIC_OPTION_H_ \ No newline at end of file diff --git a/src/common/version.cc b/src/common/version.cc index 6f93bb412..c29773f21 100644 --- a/src/common/version.cc +++ b/src/common/version.cc @@ -15,6 +15,7 @@ #include "common/version.h" #include +#include #include #include @@ -46,6 +47,11 @@ void ShowVerion() { printf("DINGOFS BUILD_TYPE:[%s]\n", FLAGS_dingofs_build_type.c_str()); } +std::string Version() { + return fmt::format("{}, build {} + {}", FLAGS_git_tag_name, + FLAGS_git_last_commit_id, FLAGS_dingofs_build_type); +} + void LogVerion() { LOG(INFO) << "DINGOFS VERSION:[" << FLAGS_major_version << "." << FLAGS_minor_version << "]"; diff --git a/src/common/version.h b/src/common/version.h index 22f121426..4d19efcea 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -57,6 +57,8 @@ DECLARE_bool(show_version); #define DINGOFS_BUILD_TYPE "unknown" #endif +std::string Version(); + void ShowVerion(); void LogVerion(); @@ -65,4 +67,4 @@ void ExposeDingoVersion(); } // namespace dingofs -#endif // DINGOFS_COMMON_VERSION_H_ \ No newline at end of file +#endif // DINGOFS_COMMON_VERSION_H_ \ No newline at end of file diff --git a/src/mds/server.h b/src/mds/server.h index 771fee90b..a5ff79fb9 100644 --- a/src/mds/server.h +++ b/src/mds/server.h @@ -36,13 +36,10 @@ #include "mds/service/fsstat_service.h" #include "mds/service/mds_service.h" #include "mds/storage/storage.h" -#include "utils/configuration.h" namespace dingofs { namespace mds { -using ::dingofs::utils::Configuration; - class Server { public: static Server& GetInstance(); diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index eac979d39..eadf19c02 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -15,7 +15,6 @@ add_subdirectory(executor) add_library(dingofs_utils - configuration.cc leaky_bucket.cc stringstatus.cc throttle.cc diff --git a/src/utils/configuration.cc b/src/utils/configuration.cc deleted file mode 100644 index a1fb5ca27..000000000 --- a/src/utils/configuration.cc +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) 2020 NetEase Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Project: Dingofs - * - * History: - * 2018/08/30 Wenyu Zhou Initial version - */ - -#include "utils/configuration.h" - -#include - -#include -#include -#include -#include - -namespace dingofs { -namespace utils { - -bool Configuration::LoadConfig() { - std::ifstream cFile(confFile_); - - if (cFile.is_open()) { - std::string line; - while (getline(cFile, line)) { - // FIXME: may not remove middle spaces - line.erase(std::remove_if(line.begin(), line.end(), isspace), line.end()); - if (line[0] == '#' || line.empty()) continue; - - int delimiterPos = line.find("="); - std::string key = line.substr(0, delimiterPos); - int commentPos = line.find("#"); - std::string value = - line.substr(delimiterPos + 1, commentPos - delimiterPos - 1); - SetValue(key, value); - } - } else { - LOG(ERROR) << "Open config file '" << confFile_ - << "' failed: " << strerror(errno); - return false; - } - - return true; -} - -bool Configuration::SaveConfig() { - // 当前先只保存配置,原文件的注释等内容先忽略 - // TODO(yyk): 后续考虑改成原文件格式不变,只修改配置值 - std::ofstream wStream(confFile_); - if (wStream.is_open()) { - for (auto& pair : config_) { - wStream << pair.first << "=" << pair.second << std::endl; - } - wStream.close(); - } else { - return false; - } - return true; -} - -void Configuration::PrintConfig() { - LOG(INFO) << std::string(30, '=') << "BEGIN" << std::string(30, '='); - for (auto& item : config_) { - LOG(INFO) << item.first << std::string(60 - item.first.size(), ' ') << ": " - << item.second; - } - LOG(INFO) << std::string(31, '=') << "END" << std::string(31, '='); -} - -void Configuration::ExposeMetric(const std::string& exposeName) { - if (!exposeName_.empty()) { - LOG(WARNING) << "Config metric has been exposed."; - return; - } - exposeName_ = exposeName; - - for (auto& config : config_) { - UpdateMetricIfExposed(config.first, config.second); - } -} - -void Configuration::UpdateMetricIfExposed(const std::string& key, - const std::string& value) { - if (exposeName_.empty()) { - return; - } - - auto it = configMetric_.find(key); - // 如果配置项不存在,则新建配置项 - if (it == configMetric_.end()) { - ConfigItemPtr configItem = std::make_shared(); - configItem->ExposeAs(exposeName_, key); - configMetric_[key] = configItem; - } - // 更新配置项 - configMetric_[key]->Set("conf_name", key); - configMetric_[key]->Set("conf_value", value); - configMetric_[key]->Update(); -} - -std::map Configuration::ListConfig() const { - return config_; -} - -void Configuration::SetConfigPath(const std::string& path) { confFile_ = path; } - -std::string Configuration::GetConfigPath() { return confFile_; } - -std::string Configuration::GetStringValue(const std::string& key) { - return GetValue(key); -} - -bool Configuration::GetStringValue(const std::string& key, std::string* out) { - return GetValue(key, out); -} - -void Configuration::SetStringValue(const std::string& key, - const std::string& value) { - SetValue(key, value); -} - -int Configuration::GetIntValue(const std::string& key, uint64_t defaultvalue) { - std::string value = GetValue(key); - return (value == "") ? defaultvalue : std::stoi(value); -} - -bool Configuration::GetIntValue(const std::string& key, int* out) { - std::string res; - if (GetValue(key, &res)) { - *out = std::stoi(res); - return true; - } - return false; -} - -bool Configuration::GetUInt32Value(const std::string& key, uint32_t* out) { - std::string res; - if (GetValue(key, &res)) { - *out = std::stoul(res); - return true; - } - return false; -} - -bool Configuration::GetUInt64Value(const std::string& key, uint64_t* out) { - std::string res; - if (GetValue(key, &res)) { - *out = std::stoull(res); - return true; - } - return false; -} - -void Configuration::SetIntValue(const std::string& key, const int value) { - SetValue(key, std::to_string(value)); -} - -void Configuration::SetUInt64Value(const std::string& key, - const uint64_t value) { - SetValue(key, std::to_string(value)); -} - -void Configuration::SetUInt32Value(const std::string& key, - const uint32_t value) { - SetValue(key, std::to_string(value)); -} - -bool Configuration::GetInt64Value(const std::string& key, int64_t* out) { - std::string res; - if (GetValue(key, &res)) { - *out = std::stoll(res); - return true; - } - - return false; -} - -void Configuration::SetInt64Value(const std::string& key, const int64_t value) { - SetValue(key, std::to_string(value)); -} - -double Configuration::GetDoubleValue(const std::string& key, - double defaultvalue) { - std::string value = GetValue(key); - return (value == "") ? defaultvalue : std::stod(value); -} - -bool Configuration::GetDoubleValue(const std::string& key, double* out) { - std::string res; - if (GetValue(key, &res)) { - *out = std::stod(res); - return true; - } - return false; -} - -void Configuration::SetDoubleValue(const std::string& key, const double value) { - SetValue(key, std::to_string(value)); -} - -double Configuration::GetFloatValue(const std::string& key, - float defaultvalue) { - std::string value = GetValue(key); - return (value == "") ? defaultvalue : std::stof(value); -} - -bool Configuration::GetFloatValue(const std::string& key, float* out) { - std::string res; - if (GetValue(key, &res)) { - *out = std::stof(res); - return true; - } - return false; -} - -void Configuration::SetFloatValue(const std::string& key, const float value) { - SetValue(key, std::to_string(value)); -} - -bool Configuration::GetBoolValue(const std::string& key, bool defaultvalue) { - std::string svalue = config_[key]; - transform(svalue.begin(), svalue.end(), svalue.begin(), ::tolower); - - bool istrue = (svalue == "true") || (svalue == "yes") || (svalue == "1"); - bool isfalse = (svalue == "false") || (svalue == "no") || (svalue == "0"); - bool ret = istrue ? true : isfalse ? false : defaultvalue; - return ret; -} - -bool Configuration::GetBoolValue(const std::string& key, bool* out) { - std::string res; - if (GetValue(key, &res)) { - transform(res.begin(), res.end(), res.begin(), ::tolower); - bool istrue = (res == "true") || (res == "yes") || (res == "1"); - bool isfalse = (res == "false") || (res == "no") || (res == "0"); - if (istrue) { - *out = true; - return true; - } - if (isfalse) { - *out = false; - return true; - } - return false; - } - - return false; -} - -void Configuration::SetBoolValue(const std::string& key, const bool value) { - SetValue(key, std::to_string(value)); -} - -std::string Configuration::GetValue(const std::string& key) { - return config_[key]; -} - -bool Configuration::GetValue(const std::string& key, std::string* out) { - if (config_.find(key) != config_.end()) { - *out = config_[key]; - return true; - } - - return false; -} - -void Configuration::SetValue(const std::string& key, const std::string& value) { - config_[key] = value; - UpdateMetricIfExposed(key, value); -} - -void Configuration::GetValueFatalIfFail(const std::string& key, int* value) { - LOG_IF(FATAL, !GetIntValue(key, value)) - << "Get " << key << " from " << confFile_ << " fail"; -} - -void Configuration::GetValueFatalIfFail(const std::string& key, - std::string* value) { - LOG_IF(FATAL, !GetStringValue(key, value)) - << "Get " << key << " from " << confFile_ << " fail"; -} - -void Configuration::GetValueFatalIfFail(const std::string& key, bool* value) { - LOG_IF(FATAL, !GetBoolValue(key, value)) - << "Get " << key << " from " << confFile_ << " fail"; -} - -void Configuration::GetValueFatalIfFail(const std::string& key, - uint32_t* value) { - LOG_IF(FATAL, !GetUInt32Value(key, value)) - << "Get " << key << " from " << confFile_ << " fail"; -} - -void Configuration::GetValueFatalIfFail(const std::string& key, - uint64_t* value) { - LOG_IF(FATAL, !GetUInt64Value(key, value)) - << "Get " << key << " from " << confFile_ << " fail"; -} - -void Configuration::GetValueFatalIfFail(const std::string& key, float* value) { - LOG_IF(FATAL, !GetFloatValue(key, value)) - << "Get " << key << " from " << confFile_ << " fail"; -} - -void Configuration::GetValueFatalIfFail(const std::string& key, double* value) { - LOG_IF(FATAL, !GetDoubleValue(key, value)) - << "Get " << key << " from " << confFile_ << " fail"; -} - -} // namespace utils -} // namespace dingofs diff --git a/src/utils/configuration.h b/src/utils/configuration.h deleted file mode 100644 index 949252274..000000000 --- a/src/utils/configuration.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2020 NetEase Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Project: Dingofs - * - * History: - * 2018/08/30 Wenyu Zhou Initial version - */ - -#include - -#include -#include -#include -#include - -#include "utils/stringstatus.h" - -#ifndef SRC_COMMON_CONFIGURATION_H_ -#define SRC_COMMON_CONFIGURATION_H_ - -namespace dingofs { -namespace utils { - -using ConfigItemPtr = std::shared_ptr; -using ConfigMetricMap = std::unordered_map; - -class Configuration { - public: - bool LoadConfig(); - bool SaveConfig(); - void PrintConfig(); - std::map ListConfig() const; - /** - * 暴露config的metric供采集 - * 如果metric已经暴露,则直接返回 - * @param exposeName: 对外暴露的metric的名字 - */ - void ExposeMetric(const std::string& exposeName); - - void SetConfigPath(const std::string& path); - std::string GetConfigPath(); - - std::string GetStringValue(const std::string& key); - /* - * @brief GetStringValue 获取指定配置项的值 - * - * @param[in] key 配置项名称 - * @param[out] out 获取的值 - * - * @return false-未获取到 true-获取成功 - */ - bool GetStringValue(const std::string& key, std::string* out); - void SetStringValue(const std::string& key, const std::string& value); - - int GetIntValue(const std::string& key, uint64_t defaultvalue = 0); - /* - * @brief GetIntValue/GetUInt32Value/GetUInt64Value 获取指定配置项的值 - * //NOLINT - * - * @param[in] key 配置项名称 - * @param[out] out 获取的值 - * - * @return false-未获取到 true-获取成功 - */ - bool GetIntValue(const std::string& key, int* out); - bool GetUInt32Value(const std::string& key, uint32_t* out); - bool GetUInt64Value(const std::string& key, uint64_t* out); - void SetIntValue(const std::string& key, const int value); - void SetUInt32Value(const std::string& key, const uint32_t value); - void SetUInt64Value(const std::string& key, const uint64_t value); - - bool GetInt64Value(const std::string& key, int64_t* out); - void SetInt64Value(const std::string& key, const int64_t value); - - double GetDoubleValue(const std::string& key, double defaultvalue = 0.0); - /* - * @brief GetDoubleValue 获取指定配置项的值 - * - * @param[in] key 配置项名称 - * @param[out] out 获取的值 - * - * @return false-未获取到 true-获取成功 - */ - bool GetDoubleValue(const std::string& key, double* out); - void SetDoubleValue(const std::string& key, const double value); - - double GetFloatValue(const std::string& key, float defaultvalue = 0.0); - /* - * @brief GetFloatValue 获取指定配置项的值 - * - * @param[in] key 配置项名称 - * @param[out] out 获取的值 - * - * @return false-未获取到 true-获取成功 - */ - bool GetFloatValue(const std::string& key, float* out); - void SetFloatValue(const std::string& key, const float value); - - bool GetBoolValue(const std::string& key, bool defaultvalue = false); - /* - * @brief GetBoolValue 获取指定配置项的值 - * - * @param[in] key 配置项名称 - * @param[out] out 获取的值 - * - * @return false-未获取到 true-获取成功 - */ - bool GetBoolValue(const std::string& key, bool* out); - void SetBoolValue(const std::string& key, const bool value); - - std::string GetValue(const std::string& key); - bool GetValue(const std::string& key, std::string* out); - void SetValue(const std::string& key, const std::string& value); - - /* - * @brief GetValueFatalIfFail 获取指定配置项的值,失败打FATAL日志 - * - * @param[in] key 配置项名称 - * @param[out] value 获取的值 - * - * @return 无 - */ - void GetValueFatalIfFail(const std::string& key, int* value); - void GetValueFatalIfFail(const std::string& key, std::string* value); - void GetValueFatalIfFail(const std::string& key, bool* value); - void GetValueFatalIfFail(const std::string& key, uint32_t* value); - void GetValueFatalIfFail(const std::string& key, uint64_t* value); - void GetValueFatalIfFail(const std::string& key, float* value); - void GetValueFatalIfFail(const std::string& key, double* value); - - bool GetValue(const std::string& key, int* value) { - return GetIntValue(key, value); - } - - bool GetValue(const std::string& key, uint32_t* value) { - return GetUInt32Value(key, value); - } - - bool GetValue(const std::string& key, int64_t* value) { - return GetInt64Value(key, value); - } - - bool GetValue(const std::string& key, uint64_t* value) { - return GetUInt64Value(key, value); - } - - bool GetValue(const std::string& key, double* value) { - return GetDoubleValue(key, value); - } - - bool GetValue(const std::string& key, float* value) { - return GetFloatValue(key, value); - } - - bool GetValue(const std::string& key, bool* value) { - return GetBoolValue(key, value); - } - - private: - /** - * 更新新的配置到metric - * @param 要更新的metric - */ - void UpdateMetricIfExposed(const std::string& key, const std::string& value); - - private: - std::string confFile_; - std::map config_; - // metric对外暴露的名字 - std::string exposeName_; - // 每一个配置项使用单独的一个metric,用map管理 - ConfigMetricMap configMetric_; -}; - -} // namespace utils -} // namespace dingofs - -#endif // SRC_COMMON_CONFIGURATION_H_ diff --git a/src/utils/gflags_helper.h b/src/utils/gflags_helper.h deleted file mode 100644 index 1f305c929..000000000 --- a/src/utils/gflags_helper.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2021 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: dingo - * Date: Friday Oct 22 17:20:07 CST 2021 - * Author: wuhanqing - */ - -#ifndef SRC_COMMON_GFLAGS_HELPER_H_ -#define SRC_COMMON_GFLAGS_HELPER_H_ - -#include -#include - -#include -#include - -#include "utils/configuration.h" - -namespace dingofs { -namespace utils { - -struct GflagsLoadValueFromConfIfCmdNotSet { - template - bool Load(const std::shared_ptr& conf, - const std::string& cmd_name, const std::string& conf_name, T* value, - bool fatal_if_missing = true) { - return Load(conf.get(), cmd_name, conf_name, value, fatal_if_missing); - } - - template - bool Load(Configuration* conf, const std::string& cmd_name, - const std::string& conf_name, ValueT* value, - bool fatal_if_missing = true) { - using ::google::CommandLineFlagInfo; - using ::google::GetCommandLineFlagInfo; - - CommandLineFlagInfo info; - if (GetCommandLineFlagInfo(cmd_name.c_str(), &info) && info.is_default) { - bool succ = conf->GetValue(conf_name, value); - if (!succ) { - if (fatal_if_missing) { - CHECK(false) << "Failed to get `" << conf_name - << "` from file: " << conf->GetConfigPath(); - } else { - LOG(WARNING) << "Failed to get `" << conf_name - << "` from file: " << conf->GetConfigPath() - << ", current value: " << *value; - return false; - } - } - } - - return true; - } -}; - -} // namespace utils -} // namespace dingofs - -#endif // SRC_COMMON_GFLAGS_HELPER_H_ diff --git a/test/unit/utils/test_configuration.cc b/test/unit/utils/test_configuration.cc deleted file mode 100644 index 784cfc263..000000000 --- a/test/unit/utils/test_configuration.cc +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (c) 2020 NetEase Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Project: Dingofs - * - * History: - * 2018/11/23 Wenyu Zhou Initial version - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "utils/configuration.h" - -namespace dingofs { -namespace utils { -namespace unit_test { - -class ConfigurationTest : public ::testing::Test { - public: - void SetUp() { - std::string confItem; - - confFile_ = "dingo.conf.test"; - std::ofstream cFile(confFile_); - ASSERT_TRUE(cFile.is_open()); - - confItem = "test.str1=teststring\n"; - cFile << confItem; - - confItem = "test.int1=12345\n"; - cFile << confItem; - - confItem = "test.int2=-2345\n"; - cFile << confItem; - - confItem = "test.int3=0\n"; - cFile << confItem; - - confItem = "test.bool1=0\n"; - cFile << confItem; - - confItem = "test.bool2=1\n"; - cFile << confItem; - - confItem = "test.bool3=false\n"; - cFile << confItem; - - confItem = "test.bool4=true\n"; - cFile << confItem; - - confItem = "test.bool5=no\n"; - cFile << confItem; - - confItem = "test.bool6=yes\n"; - cFile << confItem; - - confItem = "test.double1=3.1415926\n"; - cFile << confItem; - - confItem = "test.double2=1\n"; - cFile << confItem; - - confItem = "test.double3=1.0\n"; - cFile << confItem; - - confItem = "test.double4=0.1\n"; - cFile << confItem; - } - - void TearDown() { ASSERT_EQ(0, unlink(confFile_.c_str())); } - - std::string confFile_; -}; - -TEST_F(ConfigurationTest, SetAndGetConfigPath) { - Configuration conf; - - conf.SetConfigPath(confFile_); - ASSERT_EQ(conf.GetConfigPath(), confFile_); -} - -TEST_F(ConfigurationTest, LoadNonExistConfigFile) { - bool ret; - std::string confFile = "dingo.conf.test.nonexist"; - Configuration conf; - - conf.SetConfigPath(confFile); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, false); -} - -TEST_F(ConfigurationTest, LoadNormalConfigFile) { - bool ret; - Configuration conf; - - conf.SetConfigPath(confFile_); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); -} - -TEST_F(ConfigurationTest, ListConfig) { - Configuration conf; - - conf.SetConfigPath(confFile_); - int ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); - std::map configs; - configs = conf.ListConfig(); - ASSERT_NE(0, configs.size()); - // 抽几个key来校验以下 - ASSERT_EQ(configs["test.int1"], "12345"); - ASSERT_EQ(configs["test.bool1"], "0"); - // 如果key不存在,返回为空 - ASSERT_EQ(configs["xxx"], ""); -} - -// 覆盖原有配置 -TEST_F(ConfigurationTest, SaveConfig) { - bool ret; - Configuration conf; - conf.SetConfigPath(confFile_); - - // 自定义配置项并保存 - conf.SetStringValue("test.str1", "new"); - ret = conf.SaveConfig(); - ASSERT_EQ(ret, true); - - // 重新加载配置项 - Configuration conf2; - conf2.SetConfigPath(confFile_); - ret = conf2.LoadConfig(); - ASSERT_EQ(ret, true); - - // 可以读取自定义配置项,原有配置项被覆盖,读取不到 - ASSERT_EQ(conf2.GetValue("test.str1"), "new"); - ASSERT_EQ(conf2.GetValue("test.int1"), ""); -} - -// 读取当前配置写到其他路径 -TEST_F(ConfigurationTest, SaveConfigToFileNotExist) { - bool ret; - - // 加载当前配置 - Configuration conf; - conf.SetConfigPath(confFile_); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); - - // 写配置到其他位置 - std::string newFile("dingo.conf.test2"); - conf.SetConfigPath(newFile); - ret = conf.SaveConfig(); - ASSERT_EQ(ret, true); - - // 从新配置文件加载,并读取某项配置来进行校验 - Configuration newConf; - newConf.SetConfigPath(newFile); - ret = newConf.LoadConfig(); - ASSERT_EQ(ret, true); - ASSERT_EQ(newConf.GetValue("test.str1"), "teststring"); - - ASSERT_EQ(0, unlink(newFile.c_str())); -} - -TEST_F(ConfigurationTest, GetSetValue) { - bool ret; - Configuration conf; - - conf.SetConfigPath(confFile_); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); - - ASSERT_EQ(conf.GetValue("test.str1"), "teststring"); - ASSERT_EQ(conf.GetValue("test.int1"), "12345"); - ASSERT_EQ(conf.GetValue("test.bool1"), "0"); - ASSERT_EQ(conf.GetValue("test.str.nonexist"), ""); - - conf.SetValue("test.str1", "teststring2"); - ASSERT_EQ(conf.GetValue("test.str1"), "teststring2"); - std::string out; - ASSERT_FALSE(conf.GetValue("no.exist", &out)); - conf.SetValue("put.in", "put.in"); - ASSERT_TRUE(conf.GetValue("put.in", &out)); - ASSERT_EQ("put.in", out); -} - -TEST_F(ConfigurationTest, GetSetStringValue) { - bool ret; - Configuration conf; - - conf.SetConfigPath(confFile_); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); - - ASSERT_EQ(conf.GetStringValue("test.str1"), "teststring"); - ASSERT_EQ(conf.GetStringValue("test.int1"), "12345"); - ASSERT_EQ(conf.GetStringValue("test.bool1"), "0"); - ASSERT_EQ(conf.GetStringValue("test.str.nonexist"), ""); - - conf.SetStringValue("test.str1", "teststring2"); - ASSERT_EQ(conf.GetStringValue("test.str1"), "teststring2"); - - std::string out; - ASSERT_FALSE(conf.GetStringValue("no.exist", &out)); - conf.SetStringValue("put.in", "put.in"); - ASSERT_TRUE(conf.GetStringValue("put.in", &out)); - ASSERT_EQ("put.in", out); -} - -TEST_F(ConfigurationTest, GetSetIntValue) { - bool ret; - Configuration conf; - - conf.SetConfigPath(confFile_); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); - - ASSERT_EQ(conf.GetIntValue("test.int1"), 12345); - ASSERT_EQ(conf.GetIntValue("test.int2"), -2345); - ASSERT_EQ(conf.GetIntValue("test.int3"), 0); - ASSERT_EQ(conf.GetIntValue("test.int.nonexist"), 0); - - conf.SetIntValue("test.int1", 123); - ASSERT_EQ(conf.GetIntValue("test.int1"), 123); - - int out; - ASSERT_FALSE(conf.GetIntValue("no.exist", &out)); - conf.SetIntValue("no.exist", 1); - ASSERT_TRUE(conf.GetIntValue("no.exist", &out)); - ASSERT_EQ(1, out); - - uint32_t outu32; - ASSERT_FALSE(conf.GetUInt32Value("no.exist.u32", &outu32)); - conf.SetIntValue("no.exist.u32", 2); - ASSERT_TRUE(conf.GetUInt32Value("no.exist.u32", &outu32)); - ASSERT_EQ(2, outu32); - - uint64_t outu64; - ASSERT_FALSE(conf.GetUInt64Value("no.exist.u64", &outu64)); - conf.SetIntValue("no.exist.u64", 3); - ASSERT_TRUE(conf.GetUInt64Value("no.exist.u64", &outu64)); - ASSERT_EQ(3, outu64); - - int64_t outi64; - ASSERT_FALSE(conf.GetInt64Value("no.exist.i64", &outi64)); - conf.SetInt64Value("no.exist.i64", std::numeric_limits::min()); - ASSERT_TRUE(conf.GetInt64Value("no.exist.i64", &outi64)); - ASSERT_EQ(std::numeric_limits::min(), outi64); - conf.SetInt64Value("no.exist.i64", std::numeric_limits::max()); - ASSERT_TRUE(conf.GetInt64Value("no.exist.i64", &outi64)); - ASSERT_EQ(std::numeric_limits::max(), outi64); -} - -TEST_F(ConfigurationTest, GetSetBoolValue) { - bool ret; - Configuration conf; - - conf.SetConfigPath(confFile_); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); - - ASSERT_EQ(conf.GetBoolValue("test.bool1"), false); - ASSERT_EQ(conf.GetBoolValue("test.bool2"), true); - ASSERT_EQ(conf.GetBoolValue("test.bool3"), false); - ASSERT_EQ(conf.GetBoolValue("test.bool4"), true); - ASSERT_EQ(conf.GetBoolValue("test.bool5"), false); - ASSERT_EQ(conf.GetBoolValue("test.bool6"), true); - ASSERT_EQ(conf.GetBoolValue("test.bool.nonexist"), false); - - conf.SetBoolValue("test.bool1", true); - ASSERT_EQ(conf.GetBoolValue("test.bool1"), true); - - bool out; - ASSERT_FALSE(conf.GetBoolValue("no.exist", &out)); - conf.SetIntValue("no.exist", false); - ASSERT_TRUE(conf.GetBoolValue("no.exist", &out)); - ASSERT_FALSE(out); -} - -TEST_F(ConfigurationTest, GetSetDoubleAndFloatValue) { - bool ret; - Configuration conf; - - conf.SetConfigPath(confFile_); - ret = conf.LoadConfig(); - ASSERT_EQ(ret, true); - - ASSERT_EQ(conf.GetDoubleValue("test.double1"), 3.1415926); - ASSERT_EQ(conf.GetDoubleValue("test.double2"), 1); - ASSERT_EQ(conf.GetDoubleValue("test.double3"), 1.0); - ASSERT_EQ(conf.GetDoubleValue("test.double4"), 0.1); - ASSERT_EQ(conf.GetFloatValue("test.double4"), 0.1f); - - conf.SetDoubleValue("test.double1", 100.0); - ASSERT_EQ(conf.GetDoubleValue("test.double1"), 100.0); - - double out; - float outf; - ASSERT_FALSE(conf.GetDoubleValue("no.exist", &out)); - ASSERT_FALSE(conf.GetFloatValue("no.exist", &outf)); - conf.SetDoubleValue("no.exist", 0.009); - ASSERT_TRUE(conf.GetDoubleValue("no.exist", &out)); - ASSERT_TRUE(conf.GetFloatValue("no.exist", &outf)); - ASSERT_EQ(0.009, out); - ASSERT_EQ(0.009f, outf); -} - -TEST_F(ConfigurationTest, TestMetric) { - Configuration conf; - conf.SetIntValue("key1", 123); - conf.SetFloatValue("key2", 1.23); - - conf.ExposeMetric("conf_metric"); - ASSERT_STREQ(bvar::Variable::describe_exposed("conf_metric_key1").c_str(), - "{\"conf_name\":\"key1\",\"conf_value\":\"123\"}"); - ASSERT_STREQ(bvar::Variable::describe_exposed("conf_metric_key2").c_str(), - "{\"conf_name\":\"key2\",\"conf_value\":\"1.230000\"}"); - // 还未设置时,返回空 - ASSERT_STREQ(bvar::Variable::describe_exposed("conf_metric_key3").c_str(), - ""); - - // 支持自动更新metric - conf.SetIntValue("key1", 234); - ASSERT_STREQ(bvar::Variable::describe_exposed("conf_metric_key1").c_str(), - "{\"conf_name\":\"key1\",\"conf_value\":\"234\"}"); - conf.SetBoolValue("key3", true); - ASSERT_STREQ(bvar::Variable::describe_exposed("conf_metric_key3").c_str(), - "{\"conf_name\":\"key3\",\"conf_value\":\"1\"}"); -} - -TEST_F(ConfigurationTest, TestGetValueFatalIfFail) { - Configuration conf; - int value1; - std::string value2; - bool value3; - uint32_t value4; - uint64_t value5; - float value6; - double value7; - ASSERT_DEATH(conf.GetValueFatalIfFail("key1", &value1), ""); - ASSERT_DEATH(conf.GetValueFatalIfFail("key2", &value2), ""); - ASSERT_DEATH(conf.GetValueFatalIfFail("key3", &value3), ""); - ASSERT_DEATH(conf.GetValueFatalIfFail("key4", &value4), ""); - ASSERT_DEATH(conf.GetValueFatalIfFail("key5", &value5), ""); - ASSERT_DEATH(conf.GetValueFatalIfFail("key6", &value6), ""); - ASSERT_DEATH(conf.GetValueFatalIfFail("key7", &value7), ""); -} - -} // namespace unit_test -} // namespace utils -} // namespace dingofs