Compare commits

...

13 Commits

Author SHA1 Message Date
Hanqing Wu b6d2d3061d curvefs: add switch for fuse splice 2022-04-28 09:47:51 +08:00
h0hmj 27ed475c2c add s3.useVirtualAddressing config, default value: false 2022-04-12 12:32:08 +08:00
Hanqing Wu 29a3415f04 metaserver: fix empty configuration after load snapshot 2022-04-11 17:06:54 +08:00
lixiaocui1 97a75560a8 curvefs/client: implement lease with mds
Currently the lease only updates the txid of the partition which solves
the problem of invalidation of the txid cache in the case of multiple mounts.

Related bug issue: https://github.com/opencurve/curve/issues/1205
2022-04-11 12:29:48 +08:00
chengyi01 c1aaadf863 upgrade bazel
1. upgrade bazel to 4.2.2
2. support clang-7.0.1
3. support gcc-8.3.0
4. test in debian10
5. dockerfile can be used to make an image of the build environment

add patch:
1. 6efb0cff5f
2. 3a928ddbad
2022-04-08 15:10:17 +08:00
hzwuhongsong@corp.netease.com bcf119e41d curvefs/client: fix lru bug 2022-04-01 21:41:53 -05:00
chenwei 9428f31192 fix curvefs release read return Bad File Description 2022-03-30 17:10:43 +08:00
lixiaocui1 09df38c40f curvefs/client: fix bug issue
https://github.com/opencurve/curve/issues/1213
https://github.com/opencurve/curve/issues/1209
https://github.com/opencurve/curve/issues/1201
https://github.com/opencurve/curve/issues/1197

1. Split the persistence operations in FuseOpRelease into FuseOpFlush
2. Dentry does not use local caching when enableCto
2022-03-29 21:43:10 +08:00
lixiaocui1 0be7440b23 curvefs/client: change log level 2022-03-23 19:06:45 +08:00
xuchaojie 2833891267 docs : add curvebs write latency optimize doc 2022-03-23 19:06:45 +08:00
chenwei ef049c8964 add curvefs meta balance design doc 2022-03-23 19:06:45 +08:00
wuhanqing 36f6b0f98f docs: add curvefs volume-space design 2022-03-23 19:06:45 +08:00
chenwei 6717a1f00f curvefs/conf: modify metaserver.conf storage max quota 2022-03-23 17:25:37 +08:00
161 changed files with 3177 additions and 427 deletions

5
.bazelrc Normal file
View File

@ -0,0 +1,5 @@
build --define=with_glog=true --define=libunwind=true
build --copt -DHAVE_ZLIB=1 --copt -DGFLAGS_NS=google --copt -DUSE_BTHREAD_MUTEX
build --cxxopt -Wno-error=format-security
build:gcc7-later --cxxopt -faligned-new
build --incompatible_blacklisted_protos_requires_proto_info=false

View File

@ -1 +1 @@
0.17.2
4.2.2

View File

@ -7,15 +7,16 @@ release?= 0
only?= "*"
tag?= "curvebs:unknown"
case?= "*"
os?= "debian9"
list:
@bash util/build.sh --list
build:
@bash util/build.sh --only=$(only) --release=$(release)
@bash util/build.sh --only=$(only) --release=$(release) --os=$(os)
install:
@bash util/install.sh --prefix=$(prefix) --only=$(only)
image:
@bash util/image.sh $(tag)
@bash util/image.sh $(tag) $(os)

View File

@ -17,6 +17,20 @@
workspace(name = "curve")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# skylib
http_archive(
name = "bazel_skylib",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.2.0/bazel-skylib-1.2.0.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.0/bazel-skylib-1.2.0.tar.gz",
],
sha256 = "af87959afe497dc8dfd4c6cb66e1279cb98ccc84284619ebfec27d9c09a903de",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
git_repository(
name = "com_github_baidu_braft",
@ -32,13 +46,30 @@ bind(
# proto_library, cc_proto_library, and java_proto_library rules implicitly
# depend on @com_google_protobuf for protoc and proto runtimes.
# This statement defines the @com_google_protobuf repo.
# zlib
http_archive(
name = "com_google_protobuf",
sha256 = "cef7f1b5a7c5fba672bec2a319246e8feba471f04dcebfe362d55930ee7c1c30",
strip_prefix = "protobuf-3.5.0",
urls = ["https://github.com/google/protobuf/archive/v3.5.0.zip"],
name = "net_zlib",
build_file = "@com_google_protobuf//:third_party/zlib.BUILD",
sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1",
strip_prefix = "zlib-1.2.11",
urls = ["https://zlib.net/zlib-1.2.11.tar.gz"],
)
bind(
name = "zlib",
actual = "@net_zlib//:zlib",
)
http_archive(
name = "com_google_protobuf",
strip_prefix = "protobuf-3.6.1.3",
patch_args = ["-p1"],
patches = ["//:thirdparties/protobuf/protobuf.patch"],
sha256 = "9510dd2afc29e7245e9e884336f848c8a6600a14ae726adb6befdb4f786f0be2",
urls = ["https://github.com/google/protobuf/archive/v3.6.1.3.zip"],
)
bind(
name = "protobuf",
actual = "@com_google_protobuf//:protobuf",
@ -76,10 +107,7 @@ bind(
http_archive(
name = "com_github_gflags_gflags",
strip_prefix = "gflags-2.2.2",
urls = [
"https://mirror.bazel.build/github.com/gflags/gflags/archive/v2.2.2.tar.gz",
"https://github.com/gflags/gflags/archive/v2.2.2.tar.gz",
],
urls = ["https://github.com/gflags/gflags/archive/v2.2.2.tar.gz"],
)
bind(
@ -87,11 +115,11 @@ bind(
actual = "@com_github_gflags_gflags//:gflags",
)
new_http_archive(
http_archive(
name = "com_github_google_leveldb",
build_file = "bazel/leveldb.BUILD",
strip_prefix = "leveldb-a53934a3ae1244679f812d998a4f16f2c7f309a6",
url = "https://github.com/google/leveldb/archive/a53934a3ae1244679f812d998a4f16f2c7f309a6.tar.gz",
urls = ["https://github.com/google/leveldb/archive/a53934a3ae1244679f812d998a4f16f2c7f309a6.tar.gz"],
)
bind(
@ -142,49 +170,37 @@ bind(
new_local_repository(
name = "etcdclient",
build_file = "bazel/etcdclient.BUILD",
build_file = "external/bazel/etcdclient.BUILD",
path = "thirdparties/etcdclient",
)
new_http_archive(
http_archive(
name = "aws",
urls = [
"https://github.com/aws/aws-sdk-cpp/archive/1.7.340.tar.gz",
"https://mirror.bazel.build/github.com/aws/aws-sdk-cpp/archive/1.7.340.tar.gz",
],
urls = ["https://github.com/aws/aws-sdk-cpp/archive/1.7.340.tar.gz"],
sha256 = "2e82517045efb55409cff1408c12829d9e8aea22c1e2888529cb769b7473b0bf",
strip_prefix = "aws-sdk-cpp-1.7.340",
build_file = "//:thirdparties/aws/aws.BUILD",
)
new_http_archive(
http_archive(
name = "aws_c_common",
urls = [
"https://github.com/awslabs/aws-c-common/archive/v0.4.29.tar.gz",
"https://mirror.tensorflow.org/github.com/awslabs/aws-c-common/archive/v0.4.29.tar.gz",
],
urls = ["https://github.com/awslabs/aws-c-common/archive/v0.4.29.tar.gz"],
sha256 = "01c2a58553a37b3aa5914d9e0bf7bf14507ff4937bc5872a678892ca20fcae1f",
strip_prefix = "aws-c-common-0.4.29",
build_file = "//:thirdparties/aws/aws-c-common.BUILD",
)
new_http_archive(
http_archive(
name = "aws_c_event_stream",
urls = [
"https://github.com/awslabs/aws-c-event-stream/archive/v0.1.4.tar.gz",
"https://mirror.tensorflow.org/github.com/awslabs/aws-c-event-stream/archive/v0.1.4.tar.gz",
],
urls = ["https://github.com/awslabs/aws-c-event-stream/archive/v0.1.4.tar.gz"],
sha256 = "31d880d1c868d3f3df1e1f4b45e56ac73724a4dc3449d04d47fc0746f6f077b6",
strip_prefix = "aws-c-event-stream-0.1.4",
build_file = "//:thirdparties/aws/aws-c-event-stream.BUILD",
)
new_http_archive(
http_archive(
name = "aws_checksums",
urls = [
"https://github.com/awslabs/aws-checksums/archive/v0.1.5.tar.gz",
"https://mirror.tensorflow.org/github.com/awslabs/aws-checksums/archive/v0.1.5.tar.gz",
],
urls = ["https://github.com/awslabs/aws-checksums/archive/v0.1.5.tar.gz"],
sha256 = "6e6bed6f75cf54006b6bafb01b3b96df19605572131a2260fddaf0e87949ced0",
strip_prefix = "aws-checksums-0.1.5",
build_file = "//:thirdparties/aws/aws-checksums.BUILD",
@ -205,3 +221,11 @@ http_archive(
strip_prefix = "abseil-cpp-20210324.2",
sha256 = "59b862f50e710277f8ede96f083a5bb8d7c9595376146838b9580be90374ee1f",
)
# Bazel platform rules.
http_archive(
name = "platforms",
sha256 = "b601beaf841244de5c5a50d2b2eddd34839788000fa1be4260ce6603ca0d8eb7",
strip_prefix = "platforms-98939346da932eef0b54cf808622f5bb0928f00b",
urls = ["https://github.com/bazelbuild/platforms/archive/98939346da932eef0b54cf808622f5bb0928f00b.zip"],
)

View File

@ -51,16 +51,16 @@ curve_version=${tag_version}+${commit_id}${debug}
#step3 执行编译
# check bazel verion, bazel vesion must = 0.17.2
# check bazel verion, bazel vesion must = 4.2.2
bazel_version=`bazel version | grep "Build label" | awk '{print $3}'`
if [ -z ${bazel_version} ]
then
echo "please install bazel 0.17.2 first"
echo "please install bazel 4.2.2 first"
exit
fi
if [ ${bazel_version} != "0.17.2" ]
if [ ${bazel_version} != "4.2.2" ]
then
echo "bazel version must 0.17.2"
echo "bazel version must 4.2.2"
echo "now version is ${bazel_version}"
exit
fi

View File

@ -27,3 +27,4 @@ s3.throttle.iopsWriteLimit=5000
s3.throttle.bpsTotalMB=1280
s3.throttle.bpsReadMB=1280
s3.throttle.bpsWriteMB=1280
s3.useVirtualAddressing=false

View File

@ -120,9 +120,8 @@ CURVE_LLVM_FLAGS = [
"-Wvla",
"-Wwrite-strings",
"-Wno-float-conversion",
"-Wno-implicit-float-conversion",
"-Wno-implicit-int-float-conversion",
"-Wno-implicit-int-conversion",
"-Wno-float-conversion",
"-Wno-float-overflow-conversion",
"-Wno-shorten-64-to-32",
"-Wno-sign-conversion",
"-DNOMINMAX",
@ -146,10 +145,16 @@ CURVE_LLVM_TEST_FLAGS = [
"-Wno-used-but-marked-unused",
"-Wno-zero-as-null-pointer-constant",
"-Wno-gnu-zero-variadic-macro-arguments",
"-Wbraced-scalar-init",
]
# FIXME: temporary disabled because triggered in many places
CURVE_LLVM_DISABLED_FLGAS = [
"-Wno-c++11-narrowing",
]
CURVE_DEFAULT_COPTS = select({
"//:clang_compiler": CURVE_LLVM_FLAGS + CXX_FLAGS + BASE_FLAGS,
"//:clang_compiler": CURVE_LLVM_FLAGS + CXX_FLAGS + BASE_FLAGS + CURVE_LLVM_DISABLED_FLGAS,
"//conditions:default": CURVE_GCC_FLAGS + CXX_FLAGS + BASE_FLAGS + CURVE_GCC_DISABLED_FLGAS,
})

View File

@ -7,6 +7,7 @@ release?= 0
only?= "*"
hosts?= "*"
tag?= "curvefs:unknown"
os?= "debian9"
define deploy_begin
@bash util/deploy.sh begin
@ -31,13 +32,13 @@ define only_specify
endef
build:
@bash util/build.sh --only=$(only) --release=$(release)
@bash util/build.sh --only=$(only) --release=$(release) --os=$(os)
install:
@bash util/install.sh --prefix=$(prefix) --only=$(only)
image:
@bash util/image.sh $(tag)
@bash util/image.sh $(tag) $(os)
deploy:
$(call deploy_begin)

View File

@ -17,6 +17,13 @@ mdsOpt.rpcRetryOpt.normalRetryTimesBeforeTriggerWait=3
mdsOpt.rpcRetryOpt.waitSleepMs=1000
mdsOpt.rpcRetryOpt.addrs=127.0.0.1:6700,127.0.0.1:6701,127.0.0.1:6702 # __ANSIBLE_TEMPLATE__ {{ groups.mds | join_peer(hostvars, "mds_listen_port") }} __ANSIBLE_TEMPLATE__
#
# lease options
#
# client and mds lease time, default is 20s
mds.leaseTimesUs=20000000
mds.refreshTimesPerLease=5
#### metaCacheOpt
# Gets the number of retries for the leader
metaCacheOpt.metacacheGetLeaderRetry=3
@ -73,6 +80,11 @@ fuseClient.dCacheLruSize=65536
fuseClient.enableICacheMetrics=true
fuseClient.enableDCacheMetrics=true
fuseClient.cto=true
# splice will bring higher performance in some cases
# but there're 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
fuseClient.enableSplice=false
#### volume
volume.bigFileSize=1048576
@ -118,6 +130,7 @@ s3.throttle.iopsWriteLimit=0
s3.throttle.bpsTotalMB=0
s3.throttle.bpsReadMB=0
s3.throttle.bpsWriteMB=0
s3.useVirtualAddressing=false
# TODO(hongsong): limit bytes、iops/bps
#### disk cache options

View File

@ -124,3 +124,4 @@ s3.throttle.iopsWriteLimit=0
s3.throttle.bpsTotalMB=0
s3.throttle.bpsReadMB=0
s3.throttle.bpsWriteMB=0
s3.useVirtualAddressing=false

View File

@ -26,6 +26,7 @@ s3.throttle.iopsWriteLimit=0
s3.throttle.bpsTotalMB=0
s3.throttle.bpsReadMB=0
s3.throttle.bpsWriteMB=0
s3.useVirtualAddressing=false
# s3 workqueue
s3compactwq.enable=True
s3compactwq.thread_num=2
@ -207,7 +208,7 @@ mdsOpt.rpcRetryOpt.addrs=127.0.0.1:6700,127.0.0.1:6701,127.0.0.1:6702 # __CURVE
#
# metaserver storage data directory
storage.data_dir=/tmp/storage # __CURVEADM_TEMPLATE__ ${prefix}/data __CURVEADM_TEMPLATE__
# metaserver max memory quota bytes (default: 500GB)
storage.max_memory_quota_bytes=536870912000
# metaserver max memory quota bytes (default: 30GB)
storage.max_memory_quota_bytes=32212254720
# metaserver max disk quota bytes (default: 2TB)
storage.max_disk_quota_bytes=2199023255552

View File

@ -26,5 +26,6 @@ s3.endpoint=endpoint
s3.bucket_name=bucket
s3.blocksize=4194304
s3.chunksize=67108864
s3.useVirtualAddressing=false
# statistic info in xattr, hardlink will not be supported when enable
enableSumInDir=false

View File

@ -0,0 +1,8 @@
FROM opencurvedocker/curve-base:debian10
ENV TZ=Asia/Shanghai
RUN mkdir -p /curvefs /etc/curvefs /core
COPY curvefs /curvefs
COPY entrypoint.sh /
COPY curvefs/tools/sbin/curvefs_tool /usr/bin
RUN chmod a+x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -0,0 +1,36 @@
FROM debian:10
RUN echo "deb http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
> /etc/apt/sources.list \
&& apt-get clean \
&& apt-get -y update \
&& apt-get -y install \
gcc \
gdb \
make \
openssl \
net-tools \
libcurl3-gnutls \
perl \
linux-perf \
vim \
curl \
cron \
procps \
lsof \
nginx \
less \
fuse3 \
libnl-3-200 \
libnl-genl-3-200 \
libjemalloc2 \
&& ln -s /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so
COPY libetcdclient.so /usr/lib/

View File

@ -0,0 +1,4 @@
.PHONY: build
build:
docker build -t opencurvedocker/curve-base:debian10 .

View File

@ -0,0 +1,36 @@
FROM debian:10
RUN echo "deb http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
> /etc/apt/sources.list \
&& apt-get clean \
&& apt-get -y update \
&& apt-get -y install \
wget \
git \
gcc \
g++ \
clang \
libssl-dev \
libnl-genl-3-dev \
libcurl4-gnutls-dev \
uuid-dev \
libfiu-dev \
libfuse3-dev \
zlib1g-dev \
make \
openjdk-11-jdk \
sudo \
&& wget https://github.com/bazelbuild/bazelisk/releases/download/v1.11.0/bazelisk-linux-amd64 \
&& mv bazelisk-linux-amd64 /usr/bin/bazelisk \
&& ln -s /usr/bin/bazelisk /usr/bin/bazel \
&& wget https://github.com/bazelbuild/bazel/releases/download/4.2.2/bazel-4.2.2-linux-x86_64 \
&& mkdir -p /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin \
&& mv bazel-4.2.2-linux-x86_64 /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel \
&& chmod +x /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel /usr/bin/bazel /usr/bin/bazelisk

View File

@ -0,0 +1,4 @@
.PHONY: build
build:
docker build -t opencurvedocker/curve-base:build-debian10 .

View File

@ -0,0 +1,8 @@
FROM opencurvedocker/curve-base:debian11
ENV TZ=Asia/Shanghai
RUN mkdir -p /curvefs /etc/curvefs /core
COPY curvefs /curvefs
COPY entrypoint.sh /
COPY curvefs/tools/sbin/curvefs_tool /usr/bin
RUN chmod a+x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -0,0 +1,36 @@
FROM debian:11
RUN echo "deb http://mirrors.163.com/debian/ bullseye main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ bullseye-updates main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ bullseye-backports main non-free contrib\n" \
"deb http://mirrors.163.com/debian-security/ stable-security main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ bullseye main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ bullseye-updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ bullseye-backports main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian-security/ stable-security main non-free contrib\n" \
> /etc/apt/sources.list \
&& apt-get clean \
&& apt-get -y update \
&& apt-get -y install \
gcc \
gdb \
make \
openssl \
net-tools \
libcurl3-gnutls \
perl \
linux-perf \
vim \
curl \
cron \
procps \
lsof \
nginx \
less \
fuse3 \
libnl-3-200 \
libnl-genl-3-200 \
libjemalloc2 \
&& ln -s /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so
COPY libetcdclient.so /usr/lib/

View File

@ -0,0 +1,4 @@
.PHONY: build
build:
docker build -t opencurvedocker/curve-base:debian11 .

View File

@ -0,0 +1,36 @@
FROM debian:11
RUN echo "deb http://mirrors.163.com/debian/ bullseye main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ bullseye-updates main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ bullseye-backports main non-free contrib\n" \
"deb http://mirrors.163.com/debian-security/ stable-security main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ bullseye main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ bullseye-updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ bullseye-backports main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian-security/ stable-security main non-free contrib\n" \
> /etc/apt/sources.list \
&& apt-get clean \
&& apt-get -y update \
&& apt-get -y install \
wget \
git \
gcc \
g++ \
clang \
libssl-dev \
libnl-genl-3-dev \
libcurl4-gnutls-dev \
uuid-dev \
libfiu-dev \
libfuse3-dev \
zlib1g-dev \
make \
openjdk-11-jdk \
sudo \
&& wget https://github.com/bazelbuild/bazelisk/releases/download/v1.11.0/bazelisk-linux-amd64 \
&& mv bazelisk-linux-amd64 /usr/bin/bazelisk \
&& ln -s /usr/bin/bazelisk /usr/bin/bazel \
&& wget https://github.com/bazelbuild/bazel/releases/download/4.2.2/bazel-4.2.2-linux-x86_64 \
&& mkdir -p /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin \
&& mv bazel-4.2.2-linux-x86_64 /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel \
&& chmod +x /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel /usr/bin/bazel /usr/bin/bazelisk

View File

@ -0,0 +1,4 @@
.PHONY: build
build:
docker build -t opencurvedocker/curve-base:build-debian11 .

View File

@ -0,0 +1,120 @@
#!/usr/bin/env bash
# Copyright (C) 2021 Jingli Chen (Wine93), NetEase Inc.
############################ GLOBAL VARIABLES
g_role=""
g_args=""
g_prefix=""
g_binary=""
g_start_args=""
############################ BASIC FUNCTIONS
function msg() {
printf '%b' "$1" >&2
}
function success() {
msg "\33[32m[✔]\33[0m ${1}${2}"
}
function die() {
msg "\33[31m[✘]\33[0m ${1}${2}"
exit 1
}
############################ FUNCTIONS
function usage () {
cat << _EOC_
Usage:
entrypoint.sh --role=ROLE
entrypoint.sh --role=ROLE --args=ARGS
Examples:
entrypoint.sh --role=etcd
entrypoint.sh --role=client --args="-o default_permissions"
_EOC_
}
function get_options() {
local long_opts="role:,args:,help"
local args=`getopt -o ra --long $long_opts -n "$0" -- "$@"`
eval set -- "${args}"
while true
do
case "$1" in
-r|--role)
g_role=$2
shift 2
;;
-a|--args)
g_args=$2
shift 2
;;
-h)
usage
exit 1
;;
--)
shift
break
;;
*)
exit 1
;;
esac
done
}
function prepare() {
g_prefix="/curvefs/$g_role"
conf_path="$g_prefix/conf/$g_role.conf"
case $g_role in
etcd)
g_binary="$g_prefix/sbin/etcd"
g_start_args="--config-file $conf_path"
;;
mds)
g_binary="$g_prefix/sbin/curvefs-mds"
g_start_args="--confPath $conf_path"
;;
metaserver)
g_binary="$g_prefix/sbin/curvefs-metaserver"
g_start_args="--confPath $conf_path"
;;
client)
g_binary="$g_prefix/sbin/curve-fuse"
g_start_args="--confPath $conf_path"
;;
*)
usage
exit 1
;;
esac
if [ "$g_args" != "" ]; then
g_start_args=$g_args
fi
}
function create_directory() {
chmod 700 "$g_prefix/data"
if [ "$g_role" == "etcd" ]; then
mkdir -p "$g_prefix/data/wal"
elif [ "$g_role" == "client" ]; then
mkdir -p "$g_prefix/mnt"
fi
}
function main() {
get_options "$@"
prepare
create_directory
[[ $(command -v crontab) ]] && cron
exec $g_binary $g_start_args
}
############################ MAIN()
main "$@"

View File

@ -0,0 +1,25 @@
FROM opencurvedocker/curve-base:debian9
RUN apt-get clean \
&& apt-get -y update \
&& apt-get -y install \
g++ \
wget \
clang \
git \
libnl-genl-3-dev \
libssl-dev \
uuid-dev \
zlib1g-dev \
libcurl4-gnutls-dev \
libfiu-dev \
openjdk-8-jdk \
sudo \
&& wget https://github.com/bazelbuild/bazelisk/releases/download/v1.11.0/bazelisk-linux-amd64 \
&& mv bazelisk-linux-amd64 /usr/bin/bazelisk \
&& ln -s /usr/bin/bazelisk /usr/bin/bazel \
&& wget https://github.com/bazelbuild/bazel/releases/download/4.2.2/bazel-4.2.2-linux-x86_64 \
&& mkdir -p /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin \
&& mv bazel-4.2.2-linux-x86_64 /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel \
&& chmod +x /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel /usr/bin/bazel /usr/bin/bazelisk
COPY fuse3/* /usr/include/fuse3/

View File

@ -0,0 +1,4 @@
.PHONY: build
build:
docker build -t opencurvedocker/curve-base:build-debian9 .

View File

@ -0,0 +1,120 @@
#!/usr/bin/env bash
# Copyright (C) 2021 Jingli Chen (Wine93), NetEase Inc.
############################ GLOBAL VARIABLES
g_role=""
g_args=""
g_prefix=""
g_binary=""
g_start_args=""
############################ BASIC FUNCTIONS
function msg() {
printf '%b' "$1" >&2
}
function success() {
msg "\33[32m[✔]\33[0m ${1}${2}"
}
function die() {
msg "\33[31m[✘]\33[0m ${1}${2}"
exit 1
}
############################ FUNCTIONS
function usage () {
cat << _EOC_
Usage:
entrypoint.sh --role=ROLE
entrypoint.sh --role=ROLE --args=ARGS
Examples:
entrypoint.sh --role=etcd
entrypoint.sh --role=client --args="-o default_permissions"
_EOC_
}
function get_options() {
local long_opts="role:,args:,help"
local args=`getopt -o ra --long $long_opts -n "$0" -- "$@"`
eval set -- "${args}"
while true
do
case "$1" in
-r|--role)
g_role=$2
shift 2
;;
-a|--args)
g_args=$2
shift 2
;;
-h)
usage
exit 1
;;
--)
shift
break
;;
*)
exit 1
;;
esac
done
}
function prepare() {
g_prefix="/curvefs/$g_role"
conf_path="$g_prefix/conf/$g_role.conf"
case $g_role in
etcd)
g_binary="$g_prefix/sbin/etcd"
g_start_args="--config-file $conf_path"
;;
mds)
g_binary="$g_prefix/sbin/curvefs-mds"
g_start_args="--confPath $conf_path"
;;
metaserver)
g_binary="$g_prefix/sbin/curvefs-metaserver"
g_start_args="--confPath $conf_path"
;;
client)
g_binary="$g_prefix/sbin/curve-fuse"
g_start_args="--confPath $conf_path"
;;
*)
usage
exit 1
;;
esac
if [ "$g_args" != "" ]; then
g_start_args=$g_args
fi
}
function create_directory() {
chmod 700 "$g_prefix/data"
if [ "$g_role" == "etcd" ]; then
mkdir -p "$g_prefix/data/wal"
elif [ "$g_role" == "client" ]; then
mkdir -p "$g_prefix/mnt"
fi
}
function main() {
get_options "$@"
prepare
create_directory
[[ $(command -v crontab) ]] && cron
exec $g_binary $g_start_args
}
############################ MAIN()
main "$@"

View File

@ -46,7 +46,7 @@ cc_proto_library(
proto_library(
name = "mds_proto",
srcs = ["mds.proto"],
deps = [":curvefs_common_proto"],
deps = [":curvefs_common_proto",":curvefs_topology_proto"],
)
cc_proto_library(

View File

@ -16,6 +16,7 @@
syntax="proto2";
import "curvefs/proto/common.proto";
import "curvefs/proto/topology.proto";
package curvefs.mds;
option cc_generic_services = true;
@ -156,6 +157,15 @@ message ListClusterFsInfoResponse {
repeated FsInfo fsInfo = 1;
}
message RefreshSessionRequest {
repeated topology.PartitionTxId txIds = 1;
}
message RefreshSessionResponse {
required FSStatusCode statusCode = 1;
repeated topology.PartitionTxId latestTxIdList = 2;
}
service MdsService {
// fs interface
rpc CreateFs(CreateFsRequest) returns (CreateFsResponse);
@ -167,4 +177,7 @@ service MdsService {
rpc DeleteFs(DeleteFsRequest) returns (DeleteFsResponse);
rpc AllocateS3Chunk(AllocateS3ChunkRequest) returns (AllocateS3ChunkResponse);
rpc ListClusterFsInfo (ListClusterFsInfoRequest) returns (ListClusterFsInfoResponse);
// client lease
rpc RefreshSession(RefreshSessionRequest) returns (RefreshSessionResponse);
}

View File

@ -15,8 +15,8 @@
*/
syntax="proto2";
import "curvefs/proto/common.proto";
import "curvefs/proto/heartbeat.proto";
import "curvefs/proto/common.proto";
package curvefs.mds.topology;
option cc_generic_services = true;

View File

@ -55,6 +55,7 @@ cc_library(
"//curvefs/proto:space_cc_proto",
"//curvefs/src/client/rpcclient",
"//curvefs/src/common:curvefs_common",
"//curvefs/src/client/lease:curvefs_lease",
"//external:brpc",
"//external:gflags",
"//external:glog",

View File

@ -23,12 +23,12 @@ cc_library(
copts = CURVE_DEFAULT_COPTS,
visibility = ["//visibility:public"],
deps = [
"//curvefs/proto:curvefs_common_cc_proto",
"//external:brpc",
"//external:gflags",
"//external:glog",
"//src/client:curve_client",
"//src/common:curve_common",
"//src/common:curve_s3_adapter",
"//curvefs/proto:curvefs_common_cc_proto",
],
)

View File

@ -174,6 +174,12 @@ void InitExtentManagerOption(Configuration *conf,
&extentManagerOpt->preAllocSize);
}
void InitLeaseOpt(Configuration *conf, LeaseOpt *leaseOpt) {
conf->GetValueFatalIfFail("mds.leaseTimesUs", &leaseOpt->leaseTimeUs);
conf->GetValueFatalIfFail("mds.refreshTimesPerLease",
&leaseOpt->refreshTimesPerLease);
}
void SetBrpcOpt(Configuration *conf) {
curve::common::GflagsLoadValueFromConfIfCmdNotSet dummy;
dummy.Load(conf, "defer_close_second", "rpc.defer.close.second",
@ -191,6 +197,7 @@ void InitFuseClientOption(Configuration *conf, FuseClientOption *clientOption) {
InitS3Option(conf, &clientOption->s3Opt);
InitExtentManagerOption(conf, &clientOption->extentManagerOpt);
InitVolumeOption(conf, &clientOption->volumeOpt);
InitLeaseOpt(conf, &clientOption->leaseOpt);
conf->GetValueFatalIfFail("fuseClient.attrTimeOut",
&clientOption->attrTimeOut);
@ -214,6 +221,11 @@ void InitFuseClientOption(Configuration *conf, FuseClientOption *clientOption) {
conf->GetValueFatalIfFail("client.dummyserver.startport",
&clientOption->dummyServerStartPort);
LOG_IF(WARNING, conf->GetBoolValue("fuseClient.enableSplice",
&clientOption->enableFuseSplice))
<< "Not found `fuseClient.enableSplice` in conf, use default value `"
<< std::boolalpha << clientOption->enableFuseSplice << '`';
SetBrpcOpt(conf);
}

View File

@ -67,6 +67,12 @@ struct ExcutorOpt {
uint32_t batchLimit = 100;
};
struct LeaseOpt {
uint32_t refreshTimesPerLease = 5;
// default = 20s
uint32_t leaseTimeUs = 20000000;
};
struct SpaceAllocServerOption {
std::string spaceaddr;
uint64_t rpcTimeoutMs;
@ -144,6 +150,7 @@ struct FuseClientOption {
S3Option s3Opt;
ExtentManagerOption extentManagerOpt;
VolumeOption volumeOpt;
LeaseOpt leaseOpt;
double attrTimeOut;
double entryTimeOut;
@ -156,6 +163,8 @@ struct FuseClientOption {
bool enableDCacheMetrics;
uint32_t dummyServerStartPort;
bool enableFuseSplice = false;
};
void InitFuseClientOption(Configuration *conf, FuseClientOption *clientOption);
@ -168,6 +177,8 @@ void S3Info2FsS3Option(const curvefs::common::S3Info& s3,
void InitMdsOption(Configuration *conf, MdsOption *mdsOpt);
void InitLeaseOpt(Configuration *conf, LeaseOpt *leaseOpt);
} // namespace common
} // namespace client
} // namespace curvefs

View File

@ -55,6 +55,11 @@ DECLARE_int32(v);
namespace {
void EnableSplice(struct fuse_conn_info* conn) {
if (!g_fuseClientOption->enableFuseSplice) {
LOG(INFO) << "Fuse splice is disabled";
return;
}
if (conn->capable & FUSE_CAP_SPLICE_MOVE) {
conn->want |= FUSE_CAP_SPLICE_MOVE;
LOG(INFO) << "FUSE_CAP_SPLICE_MOVE enabled";
@ -294,11 +299,7 @@ void FuseOpRead(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
return;
}
struct fuse_bufvec bufvec;
bufvec.count = 1;
bufvec.off = 0;
bufvec.idx = 0;
bufvec.buf[0].size = rSize;
struct fuse_bufvec bufvec = FUSE_BUFVEC_INIT(rSize);
bufvec.buf[0].mem = buffer.get();
fuse_reply_data(req, &bufvec, FUSE_BUF_SPLICE_MOVE);
@ -449,3 +450,9 @@ void FuseOpFsync(fuse_req_t req, fuse_ino_t ino, int datasync,
CURVEFS_ERROR ret = g_ClientInstance->FuseOpFsync(req, ino, datasync, fi);
FuseReplyErrByErrCode(req, ret);
}
void FuseOpFlush(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) {
CURVEFS_ERROR ret = g_ClientInstance->FuseOpFlush(req, ino, fi);
FuseReplyErrByErrCode(req, ret);
}

View File

@ -30,6 +30,14 @@
using ::curvefs::metaserver::MetaStatusCode_Name;
namespace curvefs {
namespace client {
namespace common {
DECLARE_bool(enableCto);
} // namespace common
} // namespace client
} // namespace curvefs
namespace curvefs {
namespace client {
@ -38,8 +46,10 @@ using NameLockGuard = ::curve::common::GenericNameLockGuard<Mutex>;
void DentryCacheManagerImpl::InsertOrReplaceCache(const Dentry &dentry) {
std::string key = GetDentryCacheKey(dentry.parentinodeid(), dentry.name());
NameLockGuard lock(nameLock_, key);
dCache_->Put(key, dentry);
if (!curvefs::client::common::FLAGS_enableCto) {
NameLockGuard lock(nameLock_, key);
dCache_->Put(key, dentry);
}
}
void DentryCacheManagerImpl::DeleteCache(uint64_t parentId,
@ -68,7 +78,9 @@ CURVEFS_ERROR DentryCacheManagerImpl::GetDentry(uint64_t parent,
return MetaStatusCodeToCurvefsErrCode(ret);
}
dCache_->Put(key, *out);
if (!curvefs::client::common::FLAGS_enableCto) {
dCache_->Put(key, *out);
}
return CURVEFS_ERROR::OK;
}
@ -85,7 +97,9 @@ CURVEFS_ERROR DentryCacheManagerImpl::CreateDentry(const Dentry &dentry) {
return MetaStatusCodeToCurvefsErrCode(ret);
}
dCache_->Put(key, dentry);
if (!curvefs::client::common::FLAGS_enableCto) {
dCache_->Put(key, dentry);
}
return CURVEFS_ERROR::OK;
}

View File

@ -81,6 +81,9 @@ CURVEFS_ERROR FuseClient::Init(const FuseClientOption &option) {
metaCache->Init(option.metaCacheOpt, cli2Client, mdsClient_);
auto channelManager = std::make_shared<ChannelManager<MetaserverID>>();
leaseExecutor_ =
std::make_shared<LeaseExecutor>(option.leaseOpt, metaCache, mdsClient_);
uint32_t listenPort = 0;
if (!curve::common::StartBrpcDummyserver(option.dummyServerStartPort,
PORT_LIMIT, &listenPort)) {
@ -106,8 +109,17 @@ CURVEFS_ERROR FuseClient::Init(const FuseClientOption &option) {
if (ret3 != CURVEFS_ERROR::OK) {
return ret3;
}
ret3 =
dentryManager_->Init(option.dCacheLruSize, option.enableDCacheMetrics);
if (ret3 != CURVEFS_ERROR::OK) {
return ret3;
}
if (!leaseExecutor_->Start()) {
return CURVEFS_ERROR::INTERNAL;
}
return ret3;
}
@ -1288,7 +1300,7 @@ CURVEFS_ERROR FuseClient::FuseOpRelease(fuse_req_t req, fuse_ino_t ino,
ret = inodeManager_->GetInode(ino, inodeWrapper);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "inodeManager get inode fail, ret = " << ret
<< ", inodeid = " << ino;
<< ", ino: " << ino;
return ret;
}
@ -1297,10 +1309,11 @@ CURVEFS_ERROR FuseClient::FuseOpRelease(fuse_req_t req, fuse_ino_t ino,
ret = inodeWrapper->Release();
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "inodeManager release inode fail, ret = " << ret
<< ", inodeid = " << ino;
<< ", ino: " << ino;
return ret;
}
LOG(INFO) << "FuseOpRelease, ino: " << ino << " success";
return ret;
}

View File

@ -47,6 +47,8 @@
#include "src/common/concurrent/concurrent.h"
#include "curvefs/src/common/define.h"
#include "curvefs/src/client/common/common.h"
#include "curvefs/src/client/client_operator.h"
#include "curvefs/src/client/lease/lease_excutor.h"
#define DirectIOAlignemnt 512
@ -195,6 +197,10 @@ class FuseClient {
virtual CURVEFS_ERROR FuseOpFsync(fuse_req_t req, fuse_ino_t ino,
int datasync,
struct fuse_file_info* fi) = 0;
virtual CURVEFS_ERROR FuseOpFlush(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) {
return CURVEFS_ERROR::OK;
}
void SetFsInfo(std::shared_ptr<FsInfo> fsInfo) {
fsInfo_ = fsInfo;
@ -269,6 +275,8 @@ class FuseClient {
// dentry cache manager
std::shared_ptr<DentryCacheManager> dentryManager_;
std::shared_ptr<LeaseExecutor> leaseExecutor_;
// dir buffer
std::shared_ptr<DirBuffer> dirBuf_;

View File

@ -27,7 +27,7 @@
#define FUSE_USE_VERSION 34
#include <stddef.h>
#include <fuse_lowlevel.h>
#include <fuse3/fuse_lowlevel.h>
#ifdef __cplusplus
extern "C" {

View File

@ -254,53 +254,48 @@ CURVEFS_ERROR FuseS3Client::Truncate(Inode *inode, uint64_t length) {
return s3Adaptor_->Truncate(inode, length);
}
CURVEFS_ERROR FuseS3Client::FuseOpRelease(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) {
LOG(INFO) << "FuseOpRelease, ino: " << ino;
CURVEFS_ERROR FuseS3Client::FuseOpFlush(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) {
LOG(INFO) << "FuseOpFlush, ino: " << ino;
CURVEFS_ERROR ret = CURVEFS_ERROR::OK;
// if enableCto, flush all write cache both in memory cache and disk cache
if (curvefs::client::common::FLAGS_enableCto) {
ret = s3Adaptor_->FlushAllCache(ino);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "FuseOpRelease, flush all cache fail, ret = " << ret
<< ", inodeid = " << ino;
LOG(ERROR) << "FuseOpFlush, flush all cache fail, ret = " << ret
<< ", ino: " << ino;
return ret;
}
VLOG(1) << "FuseOpRelease, FlushAllCache ok";
}
VLOG(3) << "FuseOpFlush, flush to s3 ok";
std::shared_ptr<InodeWrapper> inodeWrapper;
ret = inodeManager_->GetInode(ino, inodeWrapper);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "FuseOpRelease, inodeManager get inode fail, ret = "
<< ret << ", inodeid = " << ino;
return ret;
}
std::shared_ptr<InodeWrapper> inodeWrapper;
ret = inodeManager_->GetInode(ino, inodeWrapper);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "FuseOpFlush, inodeManager get inode fail, ret = "
<< ret << ", ino: " << ino;
return ret;
}
::curve::common::UniqueLock lgGuard = inodeWrapper->GetUniqueLock();
// if enableCto, need sync inode meta
if (::curvefs::client::common::FLAGS_enableCto) {
::curve::common::UniqueLock lgGuard = inodeWrapper->GetUniqueLock();
ret = inodeWrapper->Sync();
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "FuseOpRelease, inode sync s3 chunk info fail, ret = "
<< ret << ", inodeid = " << ino;
LOG(ERROR) << "FuseOpFlush, inode sync s3 chunk info fail, ret = "
<< ret << ", ino: " << ino;
return ret;
}
// if disableCto, flush just flush data in memory
} else {
ret = s3Adaptor_->Flush(ino);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "FuseOpFlush, flush to diskcache failed, ret = "
<< ret << ", ino: " << ino;
return ret;
}
VLOG(1) << "FuseOpRelease, inode" << ino << " sync ok";
}
// update opencount
ret = inodeWrapper->Release();
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "FuseOpRelease, inodeManager release inode fail, ret = "
<< ret << ", inodeid = " << ino;
return ret;
}
LOG(INFO) << "FuseOpRelease, ino: " << ino << " success";
return ret;
LOG(INFO) << "FuseOpFlush, ino: " << ino << " flush ok";
return CURVEFS_ERROR::OK;
}
void FuseS3Client::FlushData() {

View File

@ -74,8 +74,8 @@ class FuseS3Client : public FuseClient {
CURVEFS_ERROR FuseOpFsync(fuse_req_t req, fuse_ino_t ino, int datasync,
struct fuse_file_info *fi) override;
CURVEFS_ERROR FuseOpRelease(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) override;
CURVEFS_ERROR FuseOpFlush(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) override;
private:
CURVEFS_ERROR Truncate(Inode *inode, uint64_t length) override;

View File

@ -296,6 +296,12 @@ CURVEFS_ERROR FuseVolumeClient::Truncate(Inode *inode, uint64_t length) {
return CURVEFS_ERROR::OK;
}
CURVEFS_ERROR FuseVolumeClient::FuseOpFlush(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) {
// Todo: flush data and note cto
return CURVEFS_ERROR::OK;
}
void FuseVolumeClient::FlushData() {
// TODO(xuchaojie) : flush volume data
}

View File

@ -76,7 +76,6 @@ class FuseVolumeClient : public FuseClient {
struct fuse_file_info *fi,
char *buffer,
size_t *rSize) override;
CURVEFS_ERROR FuseOpCreate(fuse_req_t req, fuse_ino_t parent,
const char *name, mode_t mode, struct fuse_file_info *fi,
fuse_entry_param *e) override;
@ -88,6 +87,9 @@ class FuseVolumeClient : public FuseClient {
CURVEFS_ERROR FuseOpFsync(fuse_req_t req, fuse_ino_t ino, int datasync,
struct fuse_file_info *fi) override;
CURVEFS_ERROR FuseOpFlush(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi) override;
private:
CURVEFS_ERROR Truncate(Inode *inode, uint64_t length) override;

View File

@ -49,7 +49,7 @@ CURVEFS_ERROR InodeCacheManagerImpl::GetInode(uint64_t inodeid,
NameLockGuard lock(nameLock_, std::to_string(inodeid));
bool ok = iCache_->Get(inodeid, &out);
if (ok) {
// if enableCto, we need and is unopen, we need reload from
// if enableCto and file is unopen, we need reload from
// metaserver
if (curvefs::client::common::FLAGS_enableCto && !out->IsOpen()) {
VLOG(6) << "InodeCacheManagerImpl, GetInode: enableCto and inode: "

View File

@ -0,0 +1,34 @@
#
# Copyright (c) 2022 NetEase Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
load("//:copts.bzl", "CURVE_DEFAULT_COPTS")
cc_library(
name = "curvefs_lease",
srcs = glob(["*.cpp"]),
hdrs = glob(["*.h"]),
copts = CURVE_DEFAULT_COPTS,
visibility = ["//visibility:public"],
deps = [
"//curvefs/proto:mds_cc_proto",
"//curvefs/src/client/rpcclient:rpcclient",
"//curvefs/src/client/common:common",
"//src/client:curve_client",
"//external:brpc",
"//external:gflags",
"//external:glog",
],
)

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2022 NetEase Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"){}
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Project: curve
* Created Date: Tue Mar 29 2022
* Author: lixiaocui
*/
#include <glog/logging.h>
#include <vector>
#include "curvefs/src/client/lease/lease_excutor.h"
using curvefs::mds::topology::PartitionTxId;
namespace curvefs {
namespace client {
LeaseExecutor::~LeaseExecutor() {
if (task_) {
task_->Stop();
task_->WaitTaskExit();
}
}
bool LeaseExecutor::Start() {
if (opt_.leaseTimeUs <= 0 || opt_.refreshTimesPerLease <= 0) {
LOG(ERROR) << "LeaseExecutor start fail. Invalid param in leaseopt, "
"leasTimesUs = "
<< opt_.leaseTimeUs
<< ", refreshTimePerLease = " << opt_.refreshTimesPerLease;
return false;
}
uint32_t interval = opt_.leaseTimeUs / opt_.refreshTimesPerLease;
task_.reset(new (std::nothrow) RefreshSessionTask(this, interval));
if (task_ == nullptr) {
LOG(ERROR) << "LeaseExecutor allocate refresh session task fail";
return false;
}
timespec abstime = butil::microseconds_from_now(interval);
brpc::PeriodicTaskManager::StartTaskAt(task_.get(), abstime);
LOG(INFO) << "LeaseExecutor for client started, lease interval is "
<< interval << "us";
return true;
}
void LeaseExecutor::Stop() {
if (task_ != nullptr) {
task_->Stop();
LOG(INFO) << "LeaseExecutor for client stop";
}
}
bool LeaseExecutor::RefreshLease() {
// get partition txid list
std::vector<PartitionTxId> txIds;
metaCache_->GetAllTxIds(&txIds);
if (txIds.empty()) {
return true;
}
// refresh from mds
std::vector<PartitionTxId> latestTxIdList;
FSStatusCode ret = mdsCli_->RefreshSession(txIds, &latestTxIdList);
if (ret != FSStatusCode::OK) {
LOG(ERROR) << "LeaseExecutor refresh session fail, ret = " << ret;
return true;
}
// update to metacache
std::for_each(latestTxIdList.begin(), latestTxIdList.end(),
[&](const PartitionTxId &item) {
metaCache_->SetTxId(item.partitionid(), item.txid());
});
return true;
}
} // namespace client
} // namespace curvefs

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2022 NetEase Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"){}
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Project: curve
* Created Date: Tue Mar 29 2022
* Author: lixiaocui
*/
#ifndef CURVEFS_SRC_CLIENT_LEASE_LEASE_EXCUTOR_H_
#define CURVEFS_SRC_CLIENT_LEASE_LEASE_EXCUTOR_H_
#include "curvefs/src/client/rpcclient/metacache.h"
#include "curvefs/src/client/rpcclient/mds_client.h"
#include "curvefs/src/client/common/config.h"
#include "src/client/lease_executor.h"
using curve::client::LeaseExecutorBase;
using curve::client::RefreshSessionTask;
using curvefs::client::common::LeaseOpt;
using curvefs::client::rpcclient::MdsClient;
using curvefs::client::rpcclient::MetaCache;
namespace curvefs {
namespace client {
class LeaseExecutor : public LeaseExecutorBase {
public:
LeaseExecutor(const LeaseOpt &opt, std::shared_ptr<MetaCache> metaCache,
std::shared_ptr<MdsClient> mdsCli)
: opt_(opt), metaCache_(metaCache), mdsCli_(mdsCli) {}
~LeaseExecutor();
bool Start();
void Stop();
/**
* refresh lease with mds and update resource
*/
bool RefreshLease() override;
private:
LeaseOpt opt_;
std::shared_ptr<MetaCache> metaCache_;
std::shared_ptr<MdsClient> mdsCli_;
std::unique_ptr<RefreshSessionTask> task_;
};
} // namespace client
} // namespace curvefs
#endif // CURVEFS_SRC_CLIENT_LEASE_LEASE_EXCUTOR_H_

View File

@ -48,6 +48,7 @@ static const struct fuse_lowlevel_ops curve_ll_oper = {
.release = FuseOpRelease,
.fsync = FuseOpFsync,
.releasedir = FuseOpReleaseDir,
.flush = FuseOpFlush,
};
int main(int argc, char *argv[]) {

View File

@ -21,7 +21,6 @@
*/
#include "curvefs/src/client/rpcclient/base_client.h"
#include "curvefs/src/client/common/extent.h"
namespace curvefs {
@ -148,6 +147,16 @@ void MDSBaseClient::AllocS3ChunkId(uint32_t fsId,
curvefs::mds::MdsService_Stub stub(channel);
stub.AllocateS3Chunk(cntl, &request, response, nullptr);
}
void MDSBaseClient::RefreshSession(const std::vector<PartitionTxId> &txIds,
RefreshSessionResponse *response,
brpc::Controller *cntl,
brpc::Channel *channel) {
RefreshSessionRequest request;
*request.mutable_txids() = {txIds.begin(), txIds.end()};
curvefs::mds::MdsService_Stub stub(channel);
stub.RefreshSession(cntl, &request, response, nullptr);
}
} // namespace rpcclient
} // namespace client
} // namespace curvefs

View File

@ -76,6 +76,8 @@ using curvefs::mds::GetFsInfoRequest;
using curvefs::mds::GetFsInfoResponse;
using curvefs::mds::MountFsRequest;
using curvefs::mds::MountFsResponse;
using curvefs::mds::RefreshSessionRequest;
using curvefs::mds::RefreshSessionResponse;
using curvefs::mds::UmountFsRequest;
using curvefs::mds::UmountFsResponse;
@ -172,6 +174,10 @@ class MDSBaseClient {
virtual void AllocS3ChunkId(uint32_t fsId,
AllocateS3ChunkResponse* response,
brpc::Controller* cntl, brpc::Channel* channel);
virtual void RefreshSession(const std::vector<PartitionTxId> &txIds,
RefreshSessionResponse *response,
brpc::Controller *cntl, brpc::Channel *channel);
};
} // namespace rpcclient

View File

@ -183,9 +183,9 @@ MdsClientImpl::CommitTx(const std::vector<PartitionTxId> &txIds) {
return static_cast<TopoStatusCode>(rc);
}
template<typename T>
template <typename T>
void GetEndPoint(const T &info, butil::EndPoint *internal,
butil::EndPoint *external) {
butil::EndPoint *external) {
const std::string &internalIp = info.internalip();
const std::string &externalIp = [&info]() {
if (info.has_externalip()) {
@ -436,6 +436,37 @@ FSStatusCode MdsClientImpl::AllocS3ChunkId(uint32_t fsId, uint64_t *chunkId) {
return ReturnError(rpcexcutor_.DoRPCTask(task, mdsOpt_.mdsMaxRetryMS));
}
FSStatusCode
MdsClientImpl::RefreshSession(const std::vector<PartitionTxId> &txIds,
std::vector<PartitionTxId> *latestTxIdList) {
auto task = RPCTask {
RefreshSessionResponse response;
mdsbasecli_->RefreshSession(txIds, &response, cntl, channel);
if (cntl->Failed()) {
LOG(WARNING) << "RefreshSession fail, errcode = "
<< cntl->ErrorCode()
<< ", error content: " << cntl->ErrorText()
<< ", log id = " << cntl->log_id();
return -cntl->ErrorCode();
}
FSStatusCode ret = response.statuscode();
if (ret != FSStatusCode::OK) {
LOG(WARNING) << "RefreshSession fail, errcode = " << ret
<< ", errmsg = " << FSStatusCode_Name(ret);
} else if (response.latesttxidlist_size() > 0) {
*latestTxIdList = {response.latesttxidlist().begin(),
response.latesttxidlist().end()};
LOG(INFO) << "RefreshSession need update partition txid list: "
<< response.DebugString();
}
return ret;
};
return ReturnError(rpcexcutor_.DoRPCTask(task, mdsOpt_.mdsMaxRetryMS));
}
FSStatusCode MdsClientImpl::ReturnError(int retcode) {
// rpc error convert to FSStatusCode::RPC_ERROR
if (retcode < 0) {

View File

@ -99,6 +99,10 @@ class MdsClient {
virtual bool ListPartition(uint32_t fsID,
std::vector<PartitionInfo> *partitionInfos) = 0;
virtual FSStatusCode AllocS3ChunkId(uint32_t fsId, uint64_t *chunkId) = 0;
virtual FSStatusCode
RefreshSession(const std::vector<PartitionTxId> &txIds,
std::vector<PartitionTxId> *latestTxIdList) = 0;
};
class MdsClientImpl : public MdsClient {
@ -142,6 +146,10 @@ class MdsClientImpl : public MdsClient {
FSStatusCode AllocS3ChunkId(uint32_t fsId, uint64_t *chunkId) override;
FSStatusCode
RefreshSession(const std::vector<PartitionTxId> &txIds,
std::vector<PartitionTxId> *latestTxIdList) override;
private:
FSStatusCode ReturnError(int retcode);

View File

@ -20,6 +20,7 @@
* Author: lixiaocui
*/
#include <algorithm>
#include <iterator>
#include <vector>
#include <map>
@ -47,6 +48,17 @@ void MetaCache::GetTxId(uint32_t partitionId, uint64_t *txId) {
}
}
void MetaCache::GetAllTxIds(std::vector<PartitionTxId> *txIds) {
ReadLockGuard r(txIdLock_);
auto iter = partitionTxId_.begin();
for (; iter != partitionTxId_.end(); iter++) {
PartitionTxId tmp;
tmp.set_partitionid(iter->first);
tmp.set_txid(iter->second);
txIds->push_back(std::move(tmp));
}
}
bool MetaCache::GetTxId(uint32_t fsId, uint64_t inodeId, uint32_t *partitionId,
uint64_t *txId) {
for (const auto &partition : partitionInfos_) {
@ -363,6 +375,12 @@ void MetaCache::DoAddPartitionAndCopyset(
// add copysetInfo
copysetInfoMap_.insert(copysetMap.begin(), copysetMap.end());
// add partitionIxid
std::for_each(partitionInfos.begin(), partitionInfos.end(),
[&](const PartitionInfo &item) {
SetTxId(item.partitionid(), item.txid());
});
}
bool MetaCache::UpdateCopysetInfoFromMDS(

View File

@ -120,6 +120,8 @@ class MetaCache {
virtual bool GetTxId(uint32_t fsId, uint64_t inodeId, uint32_t *partitionId,
uint64_t *txId);
virtual void GetAllTxIds(std::vector<PartitionTxId> *txIds);
virtual bool GetTarget(uint32_t fsID, uint64_t inodeID,
CopysetTarget *target, uint64_t *applyIndex,
bool refresh = false);

View File

@ -100,6 +100,7 @@ S3ClientAdaptorImpl::Init(const S3ClientAdaptorOption &option, S3Client *client,
}
}
}
return CURVEFS_ERROR::OK;
}

View File

@ -45,7 +45,6 @@ namespace curvefs {
namespace client {
using ::curve::common::Thread;
using curvefs::client::common::S3ClientAdaptorOption;
using curvefs::client::common::DiskCacheType;
using curvefs::metaserver::Inode;
using curvefs::metaserver::S3ChunkInfo;

View File

@ -22,6 +22,7 @@
#include "curvefs/src/client/s3/client_s3_cache_manager.h"
// #include <glog/logging.h>
#include <utility>
#include "curvefs/src/client/s3/client_s3_adaptor.h"
@ -314,7 +315,7 @@ int FileCacheManager::Read(uint64_t inodeId, uint64_t offset, uint64_t length,
::curve::common::UniqueLock lgGuard =
inodeWrapper->GetUniqueLock();
Inode* inode = inodeWrapper->GetMutableInodeUnlocked();
LOG(INFO) << "FileCacheManager::Read Inode: "
VLOG(9) << "FileCacheManager::Read Inode: "
<< inode->DebugString();
fileLen = inode->length();
for (; iter != totalRequests.end(); iter++) {
@ -580,9 +581,10 @@ class AsyncPrefetchCallback {
int ret = s3Client_->GetDiskCacheManager()->WriteReadDirect(
context->key, context->buf, context->len);
LOG_IF(ERROR, ret < 0)
<< "write read directly failed, key: " << context->key;
if (ret < 0) {
LOG_EVERY_SECOND(INFO) <<
"write read directly failed, key: " << context->key;
}
{
curve::common::LockGuard lg(fileCache->downloadMtx_);
fileCache->downloadingObj_.erase(context->key);

View File

@ -107,7 +107,7 @@ int DiskCacheBase::LoadAllCacheFile(std::set<std::string> *cachedObj) {
continue;
std::string fileName = cacheDirent->d_name;
cachedObj->emplace(fileName);
VLOG(3) << "LoadAllCacheFile obj, name = " << fileName;
VLOG(9) << "LoadAllCacheFile obj, name = " << fileName;
}
int rc = posixWrapper_->closedir(cacheDir);

View File

@ -337,27 +337,27 @@ void DiskCacheManager::TrimCache() {
SetDiskFsUsedRatio();
if (IsDiskCacheFull()) {
VLOG(3) << "disk cache full, begin trim.";
std::string cacheReadFullDir;
std::string cacheWriteFullDir;
std::string cacheReadFullDir, cacheWriteFullDir,
cacheReadFile, cacheWriteFile;
cacheReadFullDir = GetCacheReadFullDir();
cacheWriteFullDir = GetCacheWriteFullDir();
std::string cacheKey, cacheKeyBfo, cacheKeyDel;
if (!cachedObjName_->GetBack(&cacheKey)) {
VLOG(3) << "remove disk file error"
<< ", cachedObjName is empty.";
continue;
}
while (!IsDiskCacheSafe()) {
std::string cacheReadFile, cacheWriteFile;
if (cachedObjName_->Size() == 0) {
VLOG(3) << "remove disk file error"
<< ", cachedObjName is empty.";
cacheKeyDel = cacheKey;
if (!cachedObjName_->GetBefore(cacheKey, &cacheKeyBfo)) {
VLOG(3) << "obj is empty";
break;
}
std::string cacheKey;
cachedObjName_->GetBack(&cacheKey);
if (cacheKey.empty()) {
VLOG(3) << "cachekey is empty";
break;
}
VLOG(9) << "obj will be removed: " << cacheKey;
cacheReadFile = cacheReadFullDir + "/" + cacheKey;
cacheWriteFile = cacheWriteFullDir + "/" + cacheKey;
cacheKey = cacheKeyBfo;
VLOG(3) << "obj will be removed: " << cacheKeyDel;
cacheReadFile = cacheReadFullDir + "/" + cacheKeyDel;
cacheWriteFile = cacheWriteFullDir + "/" + cacheKeyDel;
struct stat statFile;
int ret;
ret = posixWrapper_->stat(cacheWriteFile.c_str(), &statFile);
@ -369,15 +369,15 @@ void DiskCacheManager::TrimCache() {
if (ret == 0) {
VLOG(3) << "do not remove this disk file"
<< ", file has not been uploaded to S3."
<< ", file is: " << cacheKey;
break;
<< ", file is: " << cacheKeyDel;
continue;
}
cachedObjName_->Remove(cacheKey);
cachedObjName_->Remove(cacheKeyDel);
struct stat statReadFile;
ret = posixWrapper_->stat(cacheReadFile.c_str(), &statReadFile);
if (ret != 0) {
VLOG(3) << "stat disk file error"
<< ", file is: " << cacheKey;
<< ", file is: " << cacheKeyDel;
continue;
}
// if remove disk file before delete cache,
@ -387,11 +387,11 @@ void DiskCacheManager::TrimCache() {
ret = posixWrapper_->remove(toDelFile);
if (ret < 0) {
LOG(ERROR)
<< "remove disk file error, file is: " << cacheKey;
<< "remove disk file error, file is: " << cacheKeyDel;
continue;
}
DecDiskUsedBytes(statReadFile.st_size);
VLOG(3) << "remove disk file success, file is: " << cacheKey;
VLOG(3) << "remove disk file success, file is: " << cacheKeyDel;
}
VLOG(3) << "trim over.";
}

View File

@ -103,7 +103,7 @@ int DiskCacheManagerImpl::WriteDiskFile(const std::string name, const char *buf,
int DiskCacheManagerImpl::WriteReadDirect(const std::string fileName,
const char *buf, uint64_t length) {
if (diskCacheManager_->IsDiskCacheFull()) {
LOG(ERROR) << "write disk file fail, disk full.";
VLOG(3) << "write disk file fail, disk full.";
return -1;
}
int ret = diskCacheManager_->WriteReadDirect(fileName, buf, length);

View File

@ -43,8 +43,6 @@ namespace client {
using curvefs::common::PosixWrapper;
class S3ClientAdaptorOption;
struct DiskCacheOption {
DiskCacheType diskCacheType;
uint64_t trimCheckIntervalSec;

View File

@ -282,7 +282,8 @@ int DiskCacheWrite::AsyncUploadFunc() {
}
toUpload.clear();
if (GetUploadFile("", &toUpload) <= 0) {
return 0;
VLOG(9) << "no need to upload";
continue;
}
VLOG(3) << "async upload file size = " << toUpload.size();
UploadFile(toUpload, nullptr);

View File

@ -563,5 +563,14 @@ void FsManager::GetAllFsInfo(
return;
}
void FsManager::RefreshSession(
const google::protobuf::RepeatedPtrField<PartitionTxId> &txIds,
google::protobuf::RepeatedPtrField<PartitionTxId> *needUpdate) {
std::vector<PartitionTxId> out;
std::vector<PartitionTxId> in = {txIds.begin(), txIds.end()};
topoManager_->GetLatestPartitionsTxId(in, &out);
*needUpdate = {out.begin(), out.end()};
}
} // namespace mds
} // namespace curvefs

View File

@ -48,12 +48,13 @@
namespace curvefs {
namespace mds {
using ::curvefs::mds::topology::TopologyManager;
using ::curvefs::mds::topology::Topology;
using ::curve::common::Thread;
using ::curve::common::InterruptibleSleeper;
using ::curve::common::Atomic;
using ::curve::common::InterruptibleSleeper;
using ::curve::common::S3Adapter;
using ::curve::common::Thread;
using ::curvefs::mds::topology::PartitionTxId;
using ::curvefs::mds::topology::Topology;
using ::curvefs::mds::topology::TopologyManager;
struct FsManagerOption {
uint32_t backEndThreadRunInterSec;
@ -177,6 +178,11 @@ class FsManager {
void GetAllFsInfo(::google::protobuf::RepeatedPtrField<
::curvefs::mds::FsInfo>* fsInfoVec);
void RefreshSession(
const google::protobuf::RepeatedPtrField<
curvefs::mds::topology::PartitionTxId> &txIds,
google::protobuf::RepeatedPtrField<PartitionTxId> *needUpdate);
private:
// return 0: ExactlySame; 1: uncomplete, -1: neither
int IsExactlySameOrCreateUnComplete(const std::string& fsName,

View File

@ -257,5 +257,16 @@ void MdsServiceImpl::ListClusterFsInfo(
return;
}
void MdsServiceImpl::RefreshSession(
::google::protobuf::RpcController *controller,
const ::curvefs::mds::RefreshSessionRequest *request,
::curvefs::mds::RefreshSessionResponse *response,
::google::protobuf::Closure *done) {
brpc::ClosureGuard guard(done);
fsManager_->RefreshSession(request->txids(),
response->mutable_latesttxidlist());
response->set_statuscode(FSStatusCode::OK);
}
} // namespace mds
} // namespace curvefs

View File

@ -82,6 +82,11 @@ class MdsServiceImpl : public MdsService {
::curvefs::mds::ListClusterFsInfoResponse* response,
::google::protobuf::Closure* done);
void RefreshSession(::google::protobuf::RpcController *controller,
const ::curvefs::mds::RefreshSessionRequest *request,
::curvefs::mds::RefreshSessionResponse *response,
::google::protobuf::Closure *done);
private:
std::shared_ptr<FsManager> fsManager_;
std::shared_ptr<ChunkIdAllocator> chunkIdAllocator_;

View File

@ -882,6 +882,22 @@ void TopologyManager::ListPartition(const ListPartitionRequest *request,
}
}
void TopologyManager::GetLatestPartitionsTxId(
const std::vector<PartitionTxId> &txIds,
std::vector<PartitionTxId> *needUpdate) {
for (auto iter = txIds.begin(); iter != txIds.end(); iter++) {
Partition out;
topology_ ->GetPartition(iter->partitionid(), &out);
if (out.GetTxId() != iter->txid()) {
PartitionTxId tmp;
tmp.set_partitionid(iter->partitionid());
tmp.set_txid(out.GetTxId());
needUpdate->push_back(std::move(tmp));
}
}
}
void TopologyManager::ListPartitionOfFs(FsIdType fsId,
std::list<PartitionInfo>* list) {
for (auto &partition : topology_->GetPartitionOfFs(fsId)) {

View File

@ -125,6 +125,10 @@ class TopologyManager {
virtual void ListPartitionOfFs(FsIdType fsId,
std::list<PartitionInfo>* list);
virtual void
GetLatestPartitionsTxId(const std::vector<PartitionTxId> &txIds,
std::vector<PartitionTxId> *needUpdate);
virtual TopoStatusCode UpdatePartitionStatus(PartitionIdType partitionId,
PartitionStatus status);

View File

@ -412,11 +412,15 @@ void CopysetNode::on_configuration_committed(const braft::Configuration& conf,
int64_t index) {
braft::Configuration oldconf;
// load snapshot also call this function, but it shouldn't increase epoch
if (index != latestLoadSnapshotIndex_) {
{
std::lock_guard<Mutex> lk(confMtx_);
oldconf = absl::exchange(conf_, conf);
epoch_.fetch_add(1, std::memory_order_acq_rel);
// load snapshot also call this function, but it shouldn't increase
// epoch
if (index != latestLoadSnapshotIndex_) {
epoch_.fetch_add(1, std::memory_order_acq_rel);
}
}
LOG(INFO) << "Copyset: " << name_

View File

@ -70,6 +70,7 @@ cc_binary(
"//curvefs/proto:metaserver_cc_proto",
"//curvefs/proto:mds_cc_proto",
"//curvefs/proto:space_cc_proto",
"//curvefs/test/client/rpcclient:rpcclient_test_mock",
"//test/client/mock:client_mock_lib",
],
linkopts = [
@ -89,14 +90,15 @@ cc_test(
),
copts = CURVE_TEST_COPTS + ["-I/usr/local/include/fuse3"],
deps = [
"//external:gtest",
"//external:gtest",
"@com_google_googletest//:gtest_main",
"//include/client:include_client",
"//curvefs/src/client:fuse_client_lib",
"//curvefs/src/client:fuse_client_lib",
"//test/client/mock:client_mock_lib",
"//curvefs/proto:metaserver_cc_proto",
"//curvefs/proto:mds_cc_proto",
"//curvefs/proto:space_cc_proto",
"//curvefs/test/client/rpcclient:rpcclient_test_mock",
"//curvefs/proto:metaserver_cc_proto",
"//curvefs/proto:mds_cc_proto",
"//curvefs/proto:space_cc_proto",
],
linkopts = ["-lfuse3",
"-L/usr/local/lib/x86_64-linux-gnu"],

View File

@ -28,7 +28,7 @@
#include "curvefs/test/client/mock_dentry_cache_mamager.h"
#include "curvefs/test/client/mock_inode_cache_manager.h"
#include "curvefs/test/client/mock_metaserver_client.h"
#include "curvefs/test/client/mock_mds_client.h"
#include "curvefs/test/client/rpcclient/mock_mds_client.h"
namespace curvefs {
namespace client {

View File

@ -28,7 +28,7 @@
#include "curvefs/test/client/mock_client_s3.h"
#include "curvefs/test/client/mock_inode_cache_manager.h"
#include "curvefs/test/client/mock_mds_client.h"
#include "curvefs/test/client/rpcclient/mock_mds_client.h"
#include "curvefs/test/client/mock_metaserver_service.h"
#include "curvefs/test/client/mock_spacealloc_service.h"
#include "src/common/curve_define.h"

View File

@ -38,7 +38,7 @@ TEST(FsCacheManagerTest, test_read_lru_cache_size) {
uint64_t dataCacheByte = 4ull * 1024 * 1024; // 4MiB
uint64_t maxReadCacheByte = 16ull * 1024 * 1024; // 16MiB
uint64_t maxWriteCacheByte = maxReadCacheByte;
char *buf = new char[smallDataCacheByte];
char *buf = new char[dataCacheByte];
S3ClientAdaptorOption option;
option.blockSize = 1 * 1024 * 1024;
option.chunkSize = 4 * 1024 * 1024;

View File

@ -0,0 +1,39 @@
#
# Copyright (c) 2022 NetEase Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
load("//:copts.bzl", "CURVE_TEST_COPTS")
cc_test(
name = "lease_test",
srcs = glob([
"*.cpp",
"*.h"],
),
copts = CURVE_TEST_COPTS,
deps = [
"//external:gtest",
"//external:gflags",
"//external:glog",
"//external:brpc",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"//curvefs/src/client/lease:curvefs_lease",
"//curvefs/test/client/rpcclient:rpcclient_test_mock",
"//curvefs/proto:mds_cc_proto",
],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2022 NetEase Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Project: curve
* Created Date: Wed Mar 31 2022
* Author: lixiaocui
*/
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <brpc/server.h>
#include "curvefs/test/client/rpcclient/mock_metacache.h"
#include "curvefs/test/client/rpcclient/mock_mds_client.h"
#include "curvefs/src/client/lease/lease_excutor.h"
using curvefs::client::rpcclient::MockMdsClient;
using curvefs::client::rpcclient::MockMetaCache;
using curvefs::mds::topology::PartitionTxId;
using ::testing::AtLeast;
using ::testing::Return;
using ::testing::SetArgPointee;
namespace curvefs {
namespace client {
class LeaseExecutorTest : public ::testing::Test {
protected:
void SetUp() override {
mdsCli_ = std::make_shared<MockMdsClient>();
metaCache_ = std::make_shared<MockMetaCache>();
}
void TearDown() override {}
protected:
std::shared_ptr<MockMdsClient> mdsCli_;
std::shared_ptr<MockMetaCache> metaCache_;
LeaseOpt opt_;
};
TEST_F(LeaseExecutorTest, test_start) {
{
LOG(INFO) << "### case1: invalid lease time ###";
opt_.leaseTimeUs = 0;
LeaseExecutor exec(opt_, metaCache_, mdsCli_);
ASSERT_FALSE(exec.Start());
}
{
LOG(INFO) << "### case2: invalid refresh times per lease ###";
opt_.refreshTimesPerLease = 0;
opt_.leaseTimeUs = 20;
LeaseExecutor exec(opt_, metaCache_, mdsCli_);
ASSERT_FALSE(exec.Start());
}
}
TEST_F(LeaseExecutorTest, test_start_stop) {
opt_.leaseTimeUs = 100000; // 100ms
opt_.refreshTimesPerLease = 5;
// prepare mock action
PartitionTxId txid;
txid.set_partitionid(1);
txid.set_txid(2);
std::vector<PartitionTxId> txIds = {txid};
EXPECT_CALL(*metaCache_, GetAllTxIds(_))
.WillOnce(SetArgPointee<0>(std::vector<PartitionTxId>{}))
.WillRepeatedly(SetArgPointee<0>(txIds));
EXPECT_CALL(*mdsCli_, RefreshSession(_, _))
.WillOnce(Return(FSStatusCode::UNKNOWN_ERROR))
.WillRepeatedly(
DoAll(SetArgPointee<1>(txIds), Return(FSStatusCode::OK)));
EXPECT_CALL(*metaCache_, SetTxId(1, 2))
.Times(AtLeast(opt_.refreshTimesPerLease));
// lease executor start
LeaseExecutor exec(opt_, metaCache_, mdsCli_);
ASSERT_TRUE(exec.Start());
std::this_thread::sleep_for(std::chrono::milliseconds(200));
ASSERT_NO_FATAL_FAILURE(exec.Stop());
// multi stoo ok
ASSERT_NO_FATAL_FAILURE(exec.Stop());
}
} // namespace client
} // namespace curvefs

View File

@ -1,95 +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: curve
* Created Date: Thur May 27 2021
* Author: xuchaojie
*/
#ifndef CURVEFS_TEST_CLIENT_MOCK_MDS_CLIENT_H_
#define CURVEFS_TEST_CLIENT_MOCK_MDS_CLIENT_H_
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <map>
#include <string>
#include <vector>
#include "curvefs/src/client/rpcclient/mds_client.h"
using ::testing::_;
using ::testing::Return;
namespace curvefs {
namespace client {
namespace rpcclient {
class MockMdsClient : public MdsClient {
public:
MockMdsClient() {}
~MockMdsClient() {}
MOCK_METHOD2(Init,
FSStatusCode(const ::curve::client::MetaServerOption& mdsOpt,
MDSBaseClient* baseclient));
MOCK_METHOD3(MountFs,
FSStatusCode(const std::string& fsName,
const std::string& mountPt, FsInfo* fsInfo));
MOCK_METHOD2(UmountFs, FSStatusCode(const std::string& fsName,
const std::string& mountPt));
MOCK_METHOD2(GetFsInfo,
FSStatusCode(const std::string& fsName, FsInfo* fsInfo));
MOCK_METHOD2(GetFsInfo, FSStatusCode(uint32_t fsId, FsInfo* fsInfo));
MOCK_METHOD2(AllocS3ChunkId,
FSStatusCode(uint32_t fsId, uint64_t* chunkId));
MOCK_METHOD1(CommitTx,
TopoStatusCode(const std::vector<PartitionTxId>& txIds));
MOCK_METHOD2(GetMetaServerInfo,
bool(const PeerAddr& addr,
CopysetPeerInfo<MetaserverID>* metaserverInfo));
MOCK_METHOD3(GetMetaServerListInCopysets,
bool(const LogicPoolID& logicalpooid,
const std::vector<CopysetID>& copysetidvec,
std::vector<CopysetInfo<MetaserverID>>* cpinfoVec));
MOCK_METHOD3(CreatePartition,
bool(uint32_t fsID, uint32_t count,
std::vector<PartitionInfo>* partitionInfos));
MOCK_METHOD2(GetCopysetOfPartitions,
bool(const std::vector<uint32_t>& partitionIDList,
std::map<uint32_t, Copyset>* copysetMap));
MOCK_METHOD2(ListPartition,
bool(uint32_t fsID,
std::vector<PartitionInfo>* partitionInfos));
};
} // namespace rpcclient
} // namespace client
} // namespace curvefs
#endif // CURVEFS_TEST_CLIENT_MOCK_MDS_CLIENT_H_

View File

@ -361,73 +361,38 @@ TEST_F(BaseClientTest, test_GetCopysetOfPartition) {
<< response.ShortDebugString();
}
// TEST_F(BaseClientTest, test_AllocExtents) {
// uint32_t fsId = 1;
// ExtentAllocInfo info;
// info.lOffset = 0;
// info.len = 1024;
// info.leftHintAvailable = true;
// info.pOffsetLeft = 0;
// info.rightHintAvailable = true;
// info.pOffsetRight = 0;
// curvefs::space::AllocateSpaceResponse resp;
// brpc::Controller cntl;
// cntl.set_timeout_ms(1000);
// brpc::Channel ch;
// ASSERT_EQ(0, ch.Init(addr_.c_str(), nullptr));
TEST_F(BaseClientTest, test_RefreshSession) {
// prepare in param
PartitionTxId tmp;
tmp.set_partitionid(1);
tmp.set_txid(2);
std::vector<PartitionTxId> txIds({tmp});
// curvefs::space::AllocateSpaceResponse response;
// auto extent = response.add_extents();
// extent->set_offset(0);
// extent->set_length(1024);
// response.set_status(curvefs::space::SpaceStatusCode::SPACE_OK);
// EXPECT_CALL(mockSpaceAllocService_, AllocateSpace(_, _, _, _))
// .WillOnce(DoAll(
// SetArgPointee<2>(response),
// Invoke(RpcService<AllocateSpaceRequest,
// AllocateSpaceResponse>)));
brpc::Controller cntl;
cntl.set_timeout_ms(1000);
brpc::Channel ch;
ASSERT_EQ(0, ch.Init(addr_.c_str(), nullptr));
RefreshSessionResponse resp;
// spacebasecli_.AllocExtents(fsId, info,
// curvefs::space::AllocateType::NONE,
// &resp, &cntl, &ch);
// ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText();
// ASSERT_TRUE(
// google::protobuf::util::MessageDifferencer::Equals(resp, response))
// << "resp:\n"
// << resp.ShortDebugString() << "response:\n"
// << response.ShortDebugString();
// }
// prepare out param
RefreshSessionResponse response;
response.set_statuscode(curvefs::mds::FSStatusCode::OK);
*response.mutable_latesttxidlist() = {txIds.begin(), txIds.end()};
// TEST_F(BaseClientTest, test_DeAllocExtents) {
// uint32_t fsId = 1;
// Extent extent;
// extent.set_offset(0);
// extent.set_length(1024);
// std::list<Extent> allocatedExtents;
// allocatedExtents.push_back(extent);
// curvefs::space::DeallocateSpaceResponse resp;
// brpc::Controller cntl;
// cntl.set_timeout_ms(1000);
// brpc::Channel ch;
// ASSERT_EQ(0, ch.Init(addr_.c_str(), nullptr));
EXPECT_CALL(mockMdsService_, RefreshSession(_, _, _, _))
.WillOnce(DoAll(
SetArgPointee<2>(response),
Invoke(RpcService<RefreshSessionRequest, RefreshSessionResponse>)));
// curvefs::space::DeallocateSpaceResponse response;
// response.set_status(curvefs::space::SpaceStatusCode::SPACE_OK);
// EXPECT_CALL(mockSpaceAllocService_, DeallocateSpace(_, _, _, _))
// .WillOnce(DoAll(
// SetArgPointee<2>(response),
// Invoke(
// RpcService<DeallocateSpaceRequest,
// DeallocateSpaceResponse>)));
mdsbasecli_.RefreshSession(txIds, &resp, &cntl, &ch);
ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText();
ASSERT_TRUE(
google::protobuf::util::MessageDifferencer::Equals(resp, response))
<< "resp:\n"
<< resp.ShortDebugString() << "response:\n"
<< response.ShortDebugString();
}
// spacebasecli_.DeAllocExtents(fsId, allocatedExtents, &resp, &cntl, &ch);
// ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText();
// ASSERT_TRUE(
// google::protobuf::util::MessageDifferencer::Equals(resp, response))
// << "resp:\n"
// << resp.ShortDebugString() << "response:\n"
// << response.ShortDebugString();
// }
} // namespace rpcclient
} // namespace client
} // namespace curvefs

View File

@ -98,6 +98,12 @@ void ListPartitionRpcFailed(uint32_t fsID, ListPartitionResponse *response,
cntl->SetFailed(112, "Not connected to");
}
void RefreshSessionRpcFailed(const std::vector<PartitionTxId> &txIds,
RefreshSessionResponse *response,
brpc::Controller *cntl, brpc::Channel *channel) {
cntl->SetFailed(112, "Not connected to");
}
bool ComparePartition(PartitionInfo first, PartitionInfo second) {
return first.fsid() == second.fsid() && first.poolid() == second.poolid() &&
first.copysetid() == second.copysetid() &&
@ -615,6 +621,53 @@ TEST_F(MdsClientImplTest, GetCopysetOfPartition) {
ASSERT_FALSE(mdsclient_.GetCopysetOfPartitions(partitionIDList, &out));
}
TEST_F(MdsClientImplTest, RefreshSession) {
// prame in
PartitionTxId tmp;
tmp.set_partitionid(1);
tmp.set_txid(2);
std::vector<PartitionTxId> txIds({tmp});
// out
std::vector<PartitionTxId> out;
RefreshSessionResponse response;
{
LOG(INFO) << "### case1: refresh session ok, no need update ###";
response.set_statuscode(FSStatusCode::OK);
EXPECT_CALL(mockmdsbasecli_, RefreshSession(_, _, _, _))
.WillOnce(SetArgPointee<1>(response));
ASSERT_FALSE(mdsclient_.RefreshSession(txIds, &out));
ASSERT_TRUE(out.empty());
}
{
LOG(INFO) << "### case2: refresh session ok, need update ###";
response.set_statuscode(FSStatusCode::OK);
*response.mutable_latesttxidlist() = {txIds.begin(), txIds.end()};
EXPECT_CALL(mockmdsbasecli_, RefreshSession(_, _, _, _))
.WillOnce(SetArgPointee<1>(response));
ASSERT_FALSE(mdsclient_.RefreshSession(txIds, &out));
ASSERT_EQ(1, out.size());
ASSERT_TRUE(
google::protobuf::util::MessageDifferencer::Equals(out[0], tmp))
<< "out:\n"
<< out[0].ShortDebugString() << "tmp:\n"
<< tmp.ShortDebugString();
}
{
LOG(INFO) << "### case3: rpc failed ###";
brpc::Controller cntl;
cntl.SetFailed(ECONNRESET, "error connect reset");
EXPECT_CALL(mockmdsbasecli_, RefreshSession(_, _, _, _))
.WillRepeatedly(Invoke(RefreshSessionRpcFailed));
ASSERT_EQ(FSStatusCode::RPC_ERROR,
mdsclient_.RefreshSession(txIds, &out));
}
}
} // namespace rpcclient
} // namespace client
} // namespace curvefs

View File

@ -220,6 +220,9 @@ TEST_F(MetaCacheTest, SetTxId) {
uint32_t fsId = 1;
uint64_t inodeId = 1;
CopysetGroupID groupId(1, 1);
std::vector<PartitionTxId> out;
metaCache_.GetAllTxIds(&out);
ASSERT_EQ(0, out.size());
// metaCache_.UpdatePartitionInfo(fsId, pInfoList_);
// metaCache_.UpdateCopysetInfo(groupId, metaServerList_);
@ -246,6 +249,10 @@ TEST_F(MetaCacheTest, SetTxId) {
succ = metaCache_.GetTxId(fsId, inodeId, &partitionId, &txId);
ASSERT_EQ(partitionId, expect.partitionID);
ASSERT_EQ(txId, 123);
// CASE 3: GetAllTxIds
metaCache_.GetAllTxIds(&out);
ASSERT_EQ(1, out.size());
}
TEST_F(MetaCacheTest, test_SelectTarget) {

View File

@ -83,6 +83,11 @@ class MockMDSBaseClient : public MDSBaseClient {
MOCK_METHOD4(ListPartition,
void(uint32_t fsID, ListPartitionResponse *response,
brpc::Controller *cntl, brpc::Channel *channel));
MOCK_METHOD4(RefreshSession,
void(const std::vector<PartitionTxId> &txIds,
RefreshSessionResponse *response, brpc::Controller *cntl,
brpc::Channel *channel));
};
} // namespace rpcclient
} // namespace client

View File

@ -86,6 +86,10 @@ class MockMdsClient : public MdsClient {
MOCK_METHOD2(ListPartition,
bool(uint32_t fsID,
std::vector<PartitionInfo>* partitionInfos));
MOCK_METHOD2(RefreshSession,
FSStatusCode(const std::vector<PartitionTxId> &txIds,
std::vector<PartitionTxId> *latestTxIdList));
};
} // namespace rpcclient
} // namespace client

View File

@ -48,6 +48,12 @@ class MockMdsService : public curvefs::mds::MdsService {
const ::curvefs::mds::GetFsInfoRequest *request,
::curvefs::mds::GetFsInfoResponse *response,
::google::protobuf::Closure *done));
MOCK_METHOD4(RefreshSession,
void(::google::protobuf::RpcController *controller,
const ::curvefs::mds::RefreshSessionRequest *request,
::curvefs::mds::RefreshSessionResponse *response,
::google::protobuf::Closure *done));
};
} // namespace rpcclient
} // namespace client

View File

@ -25,6 +25,7 @@
#include <gmock/gmock.h>
#include <string>
#include <vector>
#include "curvefs/src/client/rpcclient/metacache.h"
namespace curvefs {
@ -41,6 +42,10 @@ class MockMetaCache : public MetaCache {
MOCK_METHOD3(SelectTarget, bool(uint32_t fsID, CopysetTarget *target,
uint64_t *applyIndex));
MOCK_METHOD1(GetAllTxIds, void(std::vector<PartitionTxId> *txIds));
MOCK_METHOD2(SetTxId, void(uint32_t partitionId, uint64_t txId));
MOCK_METHOD2(UpdateApplyIndex,
void(const CopysetGroupID &groupID, uint64_t applyIndex));

View File

@ -27,6 +27,14 @@
#include "curvefs/test/client/mock_metaserver_client.h"
#include "curvefs/src/client/dentry_cache_manager.h"
namespace curvefs {
namespace client {
namespace common {
DECLARE_bool(enableCto);
} // namespace common
} // namespace client
} // namespace curvefs
namespace curvefs {
namespace client {
@ -63,6 +71,7 @@ class TestDentryCacheManager : public ::testing::Test {
};
TEST_F(TestDentryCacheManager, GetDentry) {
curvefs::client::common::FLAGS_enableCto = false;
uint64_t parent = 99;
uint64_t inodeid = 100;
const std::string name = "test";
@ -91,9 +100,22 @@ TEST_F(TestDentryCacheManager, GetDentry) {
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
ASSERT_TRUE(
google::protobuf::util::MessageDifferencer::Equals(dentryExp, out));
curvefs::client::common::FLAGS_enableCto = true;
EXPECT_CALL(*metaClient_, DeleteDentry(fsId_, parent, name))
.WillOnce(Return(MetaStatusCode::OK));
dCacheManager_->DeleteDentry(parent, name);
EXPECT_CALL(*metaClient_, GetDentry(fsId_, parent, name, _))
.WillOnce(
DoAll(SetArgPointee<3>(dentryExp), Return(MetaStatusCode::OK)));
ret = dCacheManager_->GetDentry(parent, name, &out);
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
ASSERT_TRUE(
google::protobuf::util::MessageDifferencer::Equals(dentryExp, out));
}
TEST_F(TestDentryCacheManager, CreateAndGetDentry) {
curvefs::client::common::FLAGS_enableCto = false;
uint64_t parent = 99;
uint64_t inodeid = 100;
const std::string name = "test";
@ -119,6 +141,23 @@ TEST_F(TestDentryCacheManager, CreateAndGetDentry) {
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
ASSERT_TRUE(
google::protobuf::util::MessageDifferencer::Equals(dentryExp, out));
curvefs::client::common::FLAGS_enableCto = true;
EXPECT_CALL(*metaClient_, DeleteDentry(fsId_, parent, name))
.WillOnce(Return(MetaStatusCode::OK));
dCacheManager_->DeleteDentry(parent, name);
EXPECT_CALL(*metaClient_, CreateDentry(_))
.WillOnce(Return(MetaStatusCode::OK));
EXPECT_CALL(*metaClient_, GetDentry(fsId_, parent, name, _))
.WillOnce(
DoAll(SetArgPointee<3>(dentryExp), Return(MetaStatusCode::OK)));
ret = dCacheManager_->CreateDentry(dentryExp);
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
ret = dCacheManager_->GetDentry(parent, name, &out);
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
ASSERT_TRUE(
google::protobuf::util::MessageDifferencer::Equals(dentryExp, out));
}
TEST_F(TestDentryCacheManager, DeleteDentry) {

View File

@ -30,7 +30,7 @@
#include "curvefs/test/client/mock_dentry_cache_mamager.h"
#include "curvefs/test/client/mock_extent_manager.h"
#include "curvefs/test/client/mock_inode_cache_manager.h"
#include "curvefs/test/client/mock_mds_client.h"
#include "curvefs/test/client/rpcclient/mock_mds_client.h"
#include "curvefs/test/client/mock_metaserver_client.h"
#include "curvefs/test/client/mock_space_client.h"
#include "curvefs/src/common/define.h"
@ -1944,7 +1944,7 @@ TEST_F(TestFuseS3Client, FuseOpFsync) {
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
}
TEST_F(TestFuseS3Client, FuseOpRelease) {
TEST_F(TestFuseS3Client, FuseOpFlush) {
fuse_req_t req;
fuse_ino_t ino = 1;
struct fuse_file_info *fi;
@ -1956,37 +1956,31 @@ TEST_F(TestFuseS3Client, FuseOpRelease) {
inodeWrapper->SetUid(32);
inodeWrapper->SetOpenCount(1);
LOG(INFO) << "############ case1: test do not need sync, get inode error";
curvefs::client::common::FLAGS_enableCto = false;
EXPECT_CALL(*inodeManager_, GetInode(ino, _))
.WillOnce(DoAll(SetArgReferee<1>(inodeWrapper),
Return(CURVEFS_ERROR::INTERNAL)));
ASSERT_EQ(CURVEFS_ERROR::INTERNAL, client_->FuseOpRelease(req, ino, fi));
LOG(INFO) << "############ case1: test disable cto and s3 flush fail";
curvefs::client::common::FLAGS_enableCto = false;
EXPECT_CALL(*s3ClientAdaptor_, Flush(ino))
.WillOnce(Return(CURVEFS_ERROR::UNKNOWN));
ASSERT_EQ(CURVEFS_ERROR::UNKNOWN, client_->FuseOpFlush(req, ino, fi));
LOG(INFO) << "############ case2: test do not need fsync, get inode ok";
EXPECT_CALL(*inodeManager_, GetInode(ino, _))
.WillOnce(
DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK)));
EXPECT_CALL(*metaClient_, UpdateInode(_, InodeOpenStatusChange::CLOSE))
.WillOnce(Return(MetaStatusCode::OK));
ASSERT_EQ(CURVEFS_ERROR::OK, client_->FuseOpRelease(req, ino, fi));
LOG(INFO) << "############ case2: test disable cto and flush ok";
EXPECT_CALL(*s3ClientAdaptor_, Flush(ino))
.WillOnce(Return(CURVEFS_ERROR::OK));
ASSERT_EQ(CURVEFS_ERROR::OK, client_->FuseOpFlush(req, ino, fi));
LOG(INFO) << "############ case3: test need fsync, but sync error";
LOG(INFO)
<< "############ case3: test enable cto, but flush all cache fail";
curvefs::client::common::FLAGS_enableCto = true;
EXPECT_CALL(*s3ClientAdaptor_, FlushAllCache(_))
.WillOnce(Return(CURVEFS_ERROR::UNKNOWN));
ASSERT_EQ(CURVEFS_ERROR::UNKNOWN, client_->FuseOpRelease(req, ino, fi));
ASSERT_EQ(CURVEFS_ERROR::UNKNOWN, client_->FuseOpFlush(req, ino, fi));
LOG(INFO) << "############ case4: test need fsync, and sync ok";
inodeWrapper->SetOpenCount(1);
LOG(INFO) << "############ case4: enable cto and execute ok";
EXPECT_CALL(*inodeManager_, GetInode(ino, _))
.WillOnce(
DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK)));
EXPECT_CALL(*s3ClientAdaptor_, FlushAllCache(_))
.WillOnce(Return(CURVEFS_ERROR::OK));
EXPECT_CALL(*metaClient_, UpdateInode(_, InodeOpenStatusChange::CLOSE))
.WillOnce(Return(MetaStatusCode::OK));
ASSERT_EQ(CURVEFS_ERROR::OK, client_->FuseOpRelease(req, ino, fi));
ASSERT_EQ(CURVEFS_ERROR::OK, client_->FuseOpFlush(req, ino, fi));
}
TEST_F(TestFuseS3Client, FuseOpGetXattr_NotSummaryInfo) {

View File

@ -669,5 +669,35 @@ TEST_F(FSManagerTest, backgroud_thread_deletefs_test) {
ASSERT_EQ(ret, FSStatusCode::NOT_FOUND);
}
TEST_F(FSManagerTest, test_efreshSession) {
PartitionTxId tmp;
tmp.set_partitionid(1);
tmp.set_txid(1);
{
LOG(INFO) << "### case1: partition txid need update ###";
RefreshSessionRequest request;
RefreshSessionResponse response;
std::vector<PartitionTxId> txidlist({std::move(tmp)});
*request.mutable_txids() = {txidlist.begin(), txidlist.end()};
EXPECT_CALL(*topoManager_, GetLatestPartitionsTxId(_, _))
.WillOnce(SetArgPointee<1>(txidlist));
fsManager_->RefreshSession(request.txids(),
response.mutable_latesttxidlist());
ASSERT_EQ(1, response.latesttxidlist_size());
}
{
LOG(INFO) << "### case2: partition txid do not need update ###";
RefreshSessionResponse response;
RefreshSessionRequest request;
std::vector<PartitionTxId> txidlist;
EXPECT_CALL(*topoManager_, GetLatestPartitionsTxId(_, _))
.WillOnce(SetArgPointee<1>(txidlist));
fsManager_->RefreshSession(request.txids(),
response.mutable_latesttxidlist());
ASSERT_EQ(0, response.latesttxidlist_size());
}
}
} // namespace mds
} // namespace curvefs

View File

@ -34,44 +34,47 @@
#include "curvefs/test/mds/mock/mock_cli2.h"
#include "test/common/mock_s3_adapter.h"
using ::curve::common::MockS3Adapter;
using ::curvefs::common::S3Info;
using ::curvefs::common::Volume;
using ::curvefs::mds::RefreshSessionRequest;
using ::curvefs::mds::RefreshSessionResponse;
using ::curvefs::mds::topology::CreatePartitionRequest;
using ::curvefs::mds::topology::CreatePartitionResponse;
using ::curvefs::mds::topology::DefaultIdGenerator;
using ::curvefs::mds::topology::DefaultTokenGenerator;
using ::curvefs::mds::topology::MockEtcdClient;
using ::curvefs::mds::topology::MockIdGenerator;
using ::curvefs::mds::topology::MockStorage;
using ::curvefs::mds::topology::MockTokenGenerator;
using ::curvefs::mds::topology::MockTopology;
using ::curvefs::mds::topology::MockTopologyManager;
using ::curvefs::mds::topology::TopologyIdGenerator;
using ::curvefs::mds::topology::TopologyImpl;
using ::curvefs::mds::topology::TopologyManager;
using ::curvefs::mds::topology::TopologyStorageCodec;
using ::curvefs::mds::topology::TopologyStorageEtcd;
using ::curvefs::mds::topology::TopologyTokenGenerator;
using ::curvefs::mds::topology::TopoStatusCode;
using ::curvefs::metaserver::FakeMetaserverImpl;
using ::curvefs::metaserver::copyset::GetLeaderResponse2;
using ::curvefs::metaserver::copyset::MockCliService2;
using ::curvefs::space::FakeSpaceImpl;
using ::curvefs::space::InitSpaceResponse;
using ::curvefs::space::SpaceStatusCode;
using ::testing::_;
using ::testing::AtLeast;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Matcher;
using ::testing::Mock;
using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::SaveArg;
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::Matcher;
using ::curvefs::common::S3Info;
using ::curvefs::common::Volume;
using ::curvefs::metaserver::FakeMetaserverImpl;
using ::curvefs::space::FakeSpaceImpl;
using ::curvefs::space::InitSpaceResponse;
using ::curvefs::space::SpaceStatusCode;
using ::curvefs::mds::topology::TopologyManager;
using ::curvefs::mds::topology::MockTopologyManager;
using ::curvefs::mds::topology::MockTopology;
using ::curvefs::mds::topology::MockIdGenerator;
using ::curvefs::mds::topology::MockTokenGenerator;
using ::curvefs::mds::topology::MockStorage;
using ::curvefs::mds::topology::TopologyIdGenerator;
using ::curvefs::mds::topology::DefaultIdGenerator;
using ::curvefs::mds::topology::TopologyTokenGenerator;
using ::curvefs::mds::topology::DefaultTokenGenerator;
using ::curvefs::mds::topology::MockEtcdClient;
using ::curvefs::mds::topology::MockTopologyManager;
using ::curvefs::mds::topology::TopologyStorageCodec;
using ::curvefs::mds::topology::TopologyStorageEtcd;
using ::curvefs::mds::topology::TopologyImpl;
using ::curvefs::mds::topology::CreatePartitionRequest;
using ::curvefs::mds::topology::CreatePartitionResponse;
using ::curvefs::mds::topology::TopoStatusCode;
using ::curvefs::metaserver::copyset::MockCliService2;
using ::curvefs::metaserver::copyset::GetLeaderResponse2;
using ::curve::common::MockS3Adapter;
namespace curvefs {
namespace mds {
@ -646,6 +649,29 @@ TEST_F(MdsServiceTest, test1) {
ASSERT_TRUE(false);
}
// test refresh session
cntl.Reset();
RefreshSessionRequest refreshSessionRequest;
RefreshSessionResponse refreshSessionResponse;
PartitionTxId tmp;
tmp.set_partitionid(1);
tmp.set_txid(1);
std::vector<PartitionTxId> partitionList({std::move(tmp)});
*refreshSessionRequest.mutable_txids() = {partitionList.begin(),
partitionList.end()};
EXPECT_CALL(*topoManager_, GetLatestPartitionsTxId(_, _))
.WillOnce(SetArgPointee<1>(partitionList));
stub.RefreshSession(&cntl, &refreshSessionRequest, &refreshSessionResponse,
NULL);
if (!cntl.Failed()) {
ASSERT_EQ(refreshSessionResponse.statuscode(), FSStatusCode::OK);
ASSERT_EQ(1, refreshSessionResponse.latesttxidlist_size());
} else {
LOG(ERROR) << "error = " << cntl.ErrorText();
ASSERT_TRUE(false);
}
// stop rpc server
server.Stop(10);
server.Join();

View File

@ -423,6 +423,10 @@ class MockTopologyManager : public TopologyManager {
MOCK_METHOD3(CreateCopysetNodeOnMetaServer,
bool(PoolIdType poolId, CopySetIdType copysetId,
MetaServerIdType metaServerId));
MOCK_METHOD2(GetLatestPartitionsTxId,
void(const std::vector<PartitionTxId> &txIds,
std::vector<PartitionTxId> *needUpdate));
};
} // namespace topology

View File

@ -25,6 +25,7 @@
#include <brpc/server.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <google/protobuf/util/message_differencer.h>
#include "curvefs/proto/topology.pb.h"
#include "curvefs/src/mds/common/mds_define.h"
@ -45,6 +46,7 @@ using ::testing::Invoke;
using curvefs::mds::MetaserverClient;
using curvefs::metaserver::MockMetaserverService;
using google::protobuf::util::MessageDifferencer;
class TestTopologyManager : public ::testing::Test {
protected:
@ -166,14 +168,55 @@ class TestTopologyManager : public ::testing::Test {
void PrepareAddPartition(FsIdType fsId, PoolIdType poolId,
CopySetIdType csId, PartitionIdType pId,
uint64_t idStart, uint64_t idEnd) {
uint64_t idStart, uint64_t idEnd,
uint64_t txId = 0) {
Partition partition(fsId, poolId, csId, pId, idStart, idEnd);
partition.SetTxId(txId);
EXPECT_CALL(*storage_, StoragePartition(_)).WillOnce(Return(true));
int ret = topology_->AddPartition(partition);
ASSERT_EQ(TopoStatusCode::TOPO_OK, ret)
<< "should have PrepareAddPartition()";
}
void PrepareTopo() {
FsIdType fsId = 0x01;
PoolIdType poolId = 0x11;
CopySetIdType copysetId = 0x51;
PartitionIdType pId1 = 0x61;
PartitionIdType pId2 = 0x62;
PartitionIdType pId3 = 0x63;
Pool::RedundanceAndPlaceMentPolicy policy;
policy.replicaNum = 3;
policy.copysetNum = 0;
policy.zoneNum = 3;
PrepareAddPool(poolId, "pool1", policy);
PrepareAddZone(0x21, "zone1", poolId);
PrepareAddZone(0x22, "zone2", poolId);
PrepareAddZone(0x23, "zone3", poolId);
PrepareAddServer(0x31, "server1", "127.0.0.1", 0, "127.0.0.1", 0, 0x21,
0x11);
PrepareAddServer(0x32, "server2", "127.0.0.1", 0, "127.0.0.1", 0, 0x22,
0x11);
PrepareAddServer(0x33, "server3", "127.0.0.1", 0, "127.0.0.1", 0, 0x23,
0x11);
PrepareAddMetaServer(0x41, "ms1", "token1", 0x31, "127.0.0.1", 7777,
"ip2", 8888);
PrepareAddMetaServer(0x42, "ms2", "token2", 0x32, "127.0.0.1", 7778,
"ip2", 8888);
PrepareAddMetaServer(0x43, "ms3", "token3", 0x33, "127.0.0.1", 7779,
"ip2", 8888);
std::set<MetaServerIdType> replicas;
replicas.insert(0x41);
replicas.insert(0x42);
replicas.insert(0x43);
PrepareAddCopySet(copysetId, poolId, replicas);
PrepareAddPartition(fsId, poolId, copysetId, pId1, 1, 100, 2);
PrepareAddPartition(fsId, poolId, copysetId, pId2, 1, 100, 2);
PrepareAddPartition(fsId + 1, poolId, copysetId, pId3, 1, 100, 2);
}
protected:
std::shared_ptr<MockIdGenerator> idGenerator_;
std::shared_ptr<MockTokenGenerator> tokenGenerator_;
@ -2368,6 +2411,34 @@ TEST_F(TestTopologyManager, test_ListPartition_Success) {
ASSERT_EQ(2, response.partitioninfolist().size());
}
TEST_F(TestTopologyManager, test_GetLatestPartitionsTxId) {
PrepareTopo();
PartitionIdType pId1 = 0x61;
{
LOG(INFO) << "### case1: partition need update ###";
PartitionTxId tmp;
tmp.set_partitionid(pId1);
tmp.set_txid(1);
std::vector<PartitionTxId> partitionList({tmp});
std::vector<PartitionTxId> out;
serviceManager_->GetLatestPartitionsTxId(partitionList, &out);
ASSERT_EQ(1, out.size());
ASSERT_EQ(pId1, out[0].partitionid());
ASSERT_EQ(2, out[0].txid());
}
{
LOG(INFO) << "### case2: partition no need update ###";
PartitionTxId tmp;
tmp.set_partitionid(pId1);
tmp.set_txid(2);
std::vector<PartitionTxId> partitionList({tmp});
std::vector<PartitionTxId> out;
serviceManager_->GetLatestPartitionsTxId(partitionList, &out);
ASSERT_TRUE(out.empty());
}
}
TEST_F(TestTopologyManager, test_ListPartitionOfFs_Success) {
FsIdType fsId = 0x01;
PoolIdType poolId = 0x11;

View File

@ -329,7 +329,7 @@ TEST_F(CopysetNodeRaftSnapshotTest,
EXPECT_EQ(0, node->on_snapshot_load(&reader));
EXPECT_EQ(100, node->LatestLoadSnapshotIndex());
// load snapshot doesn't change configuration and epoch
// load snapshot doesn't change epoch
std::vector<Peer> peers;
node->ListPeers(&peers);
EXPECT_EQ(3, peers.size());
@ -343,7 +343,7 @@ TEST_F(CopysetNodeRaftSnapshotTest,
node->on_configuration_committed(conf, meta.last_included_index());
peers.clear();
node->ListPeers(&peers);
EXPECT_EQ(3, peers.size());
EXPECT_EQ(1, peers.size());
EXPECT_EQ(epochBefore, node->GetConfEpoch());
node->SetMetaStore(nullptr);
}

View File

@ -145,7 +145,7 @@ void Init() {
}
void Run() {
thread_local unsigned int seed = time(nullptr);
static thread_local unsigned int seed = time(nullptr);
while (true) {
if (rand_r(&seed) % 4 == 0 ||
noSpace.load(std::memory_order_relaxed) == true) {

View File

@ -17,6 +17,8 @@ g_build_opts=(
"--copt -DUSE_BTHREAD_MUTEX"
)
g_os="debian9"
############################ BASIC FUNCTIONS
get_version() {
#get tag version
@ -81,7 +83,7 @@ _EOC_
}
get_options() {
local args=`getopt -o lorh --long list,only:,release: -n "$0" -- "$@"`
local args=`getopt -o lorh --long list,only:,os:,release: -n "$0" -- "$@"`
eval set -- "${args}"
while true
do
@ -98,6 +100,10 @@ get_options() {
g_release=$2
shift 2
;;
--os)
g_os=$2
shift 2
;;
-h)
usage
exit 1
@ -137,6 +143,10 @@ build_target() {
# set version
g_build_opts+=("--copt -DCURVEVERSION=${curve_version}")
if [ "$g_os" == "debian10" -o "$g_os" == "debian11" ]; then
g_build_opts+=("--config=gcc7-later")
fi
for target in `get_target`
do
bazel build ${g_build_opts[@]} $target

View File

@ -1,6 +1,7 @@
#!/usr/bin/env bash
# tmpl.sh = /usr/local/metaserver.conf /tmp/metaserver.conf
# $1: tag $2: os
function tmpl() {
dsv=$1
src=$2
@ -15,7 +16,7 @@ function tmpl() {
done < $src > $dst
}
prefix="$(pwd)/docker/curvefs"
prefix="$(pwd)/docker/$2/curvefs"
mkdir -p $prefix $prefix/conf
make install prefix="$prefix"
make install prefix="$prefix" only=etcd
@ -29,5 +30,5 @@ do
tmpl $dsv "conf/$file" "$prefix/conf/$file"
done
docker pull opencurvedocker/curve-base:debian9
docker build -t "$1" "$(pwd)/docker"
docker pull opencurvedocker/curve-base:$2
docker build -t "$1" "$(pwd)/docker/$2"

View File

@ -0,0 +1,8 @@
FROM opencurvedocker/curve-base:debian10
ENV TZ=Asia/Shanghai
RUN mkdir -p /curvebs /etc/curve /etc/nebd /core
COPY curvebs /curvebs
COPY entrypoint.sh exec.sh /
COPY curvebs/tools/sbin/curve_ops_tool curvebs/nbd/sbin/curve-nbd /usr/bin/
RUN chmod a+x /entrypoint.sh /exec.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -0,0 +1,35 @@
FROM debian:10
RUN echo "deb http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
> /etc/apt/sources.list \
&& apt-get clean \
&& apt-get -y update \
&& apt-get -y install \
gcc \
gdb \
make \
openssl \
net-tools \
libcurl3-gnutls \
perl \
linux-perf \
vim \
curl \
cron \
procps \
lsof \
nginx \
less \
fuse \
libnl-3-200 \
libnl-genl-3-200 \
libjemalloc2
COPY libetcdclient.so /usr/lib/

View File

@ -0,0 +1,4 @@
.PHONY: build
build:
docker build -t opencurvedocker/curve-base:debian10 .

View File

@ -0,0 +1,36 @@
FROM debian:10
RUN echo "deb http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-updates main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian/ buster-backports main non-free contrib\n" \
"deb-src http://mirrors.163.com/debian-security/ buster/updates main non-free contrib\n" \
> /etc/apt/sources.list \
&& apt-get clean \
&& apt-get -y update \
&& apt-get -y install \
wget \
git \
gcc \
g++ \
clang \
libssl-dev \
libnl-genl-3-dev \
libcurl4-gnutls-dev \
uuid-dev \
libfiu-dev \
libfuse3-dev \
zlib1g-dev \
make \
openjdk-11-jdk \
sudo \
&& wget https://github.com/bazelbuild/bazelisk/releases/download/v1.11.0/bazelisk-linux-amd64 \
&& mv bazelisk-linux-amd64 /usr/bin/bazelisk \
&& ln -s /usr/bin/bazelisk /usr/bin/bazel \
&& wget https://github.com/bazelbuild/bazel/releases/download/4.2.2/bazel-4.2.2-linux-x86_64 \
&& mkdir -p /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin \
&& mv bazel-4.2.2-linux-x86_64 /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel \
&& chmod +x /root/.cache/bazelisk/downloads/bazelbuild/bazel-4.2.2-linux-x86_64/bin/bazel /usr/bin/bazel /usr/bin/bazelisk

Some files were not shown because too many files have changed in this diff Show More