From 04701122f73b683f08c8f6243f66a65ad99095b7 Mon Sep 17 00:00:00 2001 From: Hanqing Wu Date: Wed, 13 Apr 2022 10:40:15 +0800 Subject: [PATCH 1/2] support generate compile_commands.json --- .gitignore | 5 + WORKSPACE | 27 +++-- external/bazel/gflags.BUILD | 34 ------- external/bazel/glog.BUILD | 98 ------------------- external/bazel/gtest.BUILD | 30 ------ external/bazel/leveldb.BUILD | 98 ------------------- .../bazel => thirdparties}/etcdclient.BUILD | 0 {external/bazel => thirdparties}/gmock.BUILD | 0 .../bazel => thirdparties}/jsoncpp.BUILD | 0 .../bazel => thirdparties}/rocksdb.BUILD | 0 10 files changed, 25 insertions(+), 267 deletions(-) delete mode 100644 external/bazel/gflags.BUILD delete mode 100644 external/bazel/glog.BUILD delete mode 100644 external/bazel/gtest.BUILD delete mode 100644 external/bazel/leveldb.BUILD rename {external/bazel => thirdparties}/etcdclient.BUILD (100%) rename {external/bazel => thirdparties}/gmock.BUILD (100%) rename {external/bazel => thirdparties}/jsoncpp.BUILD (100%) rename {external/bazel => thirdparties}/rocksdb.BUILD (100%) diff --git a/.gitignore b/.gitignore index 8bde111260..d8b0291558 100755 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,8 @@ __not_found__ thirdparties/rocksdb/lib/ thirdparties/rocksdb/include/ thirdparties/rocksdb/rocksdb/ + +/external +/bazel-* +/compile_commands.json +/.cache/ diff --git a/WORKSPACE b/WORKSPACE index eb1d8a5f58..625aada675 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -16,8 +16,7 @@ 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:git.bzl", "git_repository", "new_git_repository") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # skylib @@ -78,7 +77,7 @@ bind( #import the gtest files. new_git_repository( name = "com_google_googletest", - build_file = "bazel/gmock.BUILD", + build_file = "//:thirdparties/gmock.BUILD", remote = "https://github.com/google/googletest", tag = "release-1.8.0", ) @@ -117,7 +116,7 @@ bind( http_archive( name = "com_github_google_leveldb", - build_file = "bazel/leveldb.BUILD", + build_file = "@com_github_apache_brpc//:leveldb.BUILD", strip_prefix = "leveldb-a53934a3ae1244679f812d998a4f16f2c7f309a6", urls = ["https://github.com/google/leveldb/archive/a53934a3ae1244679f812d998a4f16f2c7f309a6.tar.gz"], ) @@ -158,7 +157,7 @@ bind( # jsoncpp new_git_repository( name = "jsoncpp", - build_file = "bazel/jsoncpp.BUILD", + build_file = "//:thirdparties/jsoncpp.BUILD", remote = "https://github.com/open-source-parsers/jsoncpp.git", tag = "1.8.4", ) @@ -170,7 +169,7 @@ bind( new_local_repository( name = "etcdclient", - build_file = "external/bazel/etcdclient.BUILD", + build_file = "//:thirdparties/etcdclient.BUILD", path = "thirdparties/etcdclient", ) @@ -233,6 +232,20 @@ http_archive( # RocksDB new_local_repository( name = "rocksdb", - build_file = "external/bazel/rocksdb.BUILD", + build_file = "//:thirdparties/rocksdb.BUILD", path = "thirdparties/rocksdb", ) + +# Hedron's Compile Commands Extractor for Bazel +# https://github.com/hedronvision/bazel-compile-commands-extractor +http_archive( + name = "hedron_compile_commands", + + # Replace the commit hash in both places (below) with the latest, rather than using the stale one here. + # Even better, set up Renovate and let it do the work for you (see "Suggestion: Updates" in the README). + url = "https://github.com/hedronvision/bazel-compile-commands-extractor/archive/af9af15f7bc16fc3e407e2231abfcb62907d258f.tar.gz", + strip_prefix = "bazel-compile-commands-extractor-af9af15f7bc16fc3e407e2231abfcb62907d258f", + # When you first run this tool, it'll recommend a sha256 hash to put here with a message like: "DEBUG: Rule 'hedron_compile_commands' indicated that a canonical reproducible form can be obtained by modifying arguments sha256 = ..." +) +load("@hedron_compile_commands//:workspace_setup.bzl", "hedron_compile_commands_setup") +hedron_compile_commands_setup() diff --git a/external/bazel/gflags.BUILD b/external/bazel/gflags.BUILD deleted file mode 100644 index de6d2d020f..0000000000 --- a/external/bazel/gflags.BUILD +++ /dev/null @@ -1,34 +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. -# - -# Bazel (http://bazel.io/) BUILD file for gflags. -# -# See INSTALL.md for instructions for adding gflags to a Bazel workspace. - -licenses(["notice"]) - -exports_files(["src/gflags_completions.sh", "COPYING.txt"]) - -config_setting( - name = "x64_windows", - values = {"cpu": "x64_windows"}, -) - -load(":bazel/gflags.bzl", "gflags_sources", "gflags_library") - -(hdrs, srcs) = gflags_sources(namespace=["gflags", "google"]) -gflags_library(hdrs=hdrs, srcs=srcs, threads=0) -gflags_library(hdrs=hdrs, srcs=srcs, threads=1) diff --git a/external/bazel/glog.BUILD b/external/bazel/glog.BUILD deleted file mode 100644 index 77d88ea7ff..0000000000 --- a/external/bazel/glog.BUILD +++ /dev/null @@ -1,98 +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. -# - -cc_library( - name = "glog", - srcs = [ - "config.h", - "src/base/commandlineflags.h", - "src/base/googleinit.h", - "src/base/mutex.h", - "src/demangle.cc", - "src/demangle.h", - "src/logging.cc", - "src/raw_logging.cc", - "src/signalhandler.cc", - "src/symbolize.cc", - "src/symbolize.h", - "src/utilities.cc", - "src/utilities.h", - "src/vlog_is_on.cc", - ] + glob(["src/stacktrace*.h"]), - hdrs = [ - "src/glog/log_severity.h", - "src/glog/logging.h", - "src/glog/raw_logging.h", - "src/glog/stl_logging.h", - "src/glog/vlog_is_on.h", - ], - copts = [ - "-Wno-sign-compare", - "-U_XOPEN_SOURCE", - ], - includes = ["./src"], - linkopts = ["-lpthread"] + select({ - ":libunwind": ["-lunwind"], - "//conditions:default": [], - }), - visibility = ["//visibility:public"], - deps = [ - "@com_github_gflags_gflags//:gflags", - ], -) - -config_setting( - name = "libunwind", - values = { - "define": "libunwind=true", - }, -) - -genrule( - name = "run_configure", - srcs = [ - "README", - "Makefile.in", - "config.guess", - "config.sub", - "install-sh", - "ltmain.sh", - "missing", - "libglog.pc.in", - "src/config.h.in", - "src/glog/logging.h.in", - "src/glog/raw_logging.h.in", - "src/glog/stl_logging.h.in", - "src/glog/vlog_is_on.h.in", - ], - outs = [ - "config.h", - "src/glog/logging.h", - "src/glog/raw_logging.h", - "src/glog/stl_logging.h", - "src/glog/vlog_is_on.h", - ], - tools = [ - "configure", - ], - cmd = "$(location :configure)" + - "&& cp -v src/config.h $(location config.h) " + - "&& cp -v src/glog/logging.h $(location src/glog/logging.h) " + - "&& cp -v src/glog/raw_logging.h $(location src/glog/raw_logging.h) " + - "&& cp -v src/glog/stl_logging.h $(location src/glog/stl_logging.h) " + - "&& cp -v src/glog/vlog_is_on.h $(location src/glog/vlog_is_on.h) " - , -) diff --git a/external/bazel/gtest.BUILD b/external/bazel/gtest.BUILD deleted file mode 100644 index f88075d55b..0000000000 --- a/external/bazel/gtest.BUILD +++ /dev/null @@ -1,30 +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. -# - -cc_library( - name = "main", - srcs = glob( - ["src/*.cc"], - exclude = ["src/gtest-all.cc"] - ), - hdrs = glob([ - "include/**/*.h", - "src/*.h" - ]), - copts = ["-Iexternal/gtest/include"], - linkopts = ["-pthread"], - visibility = ["//visibility:public"], -) diff --git a/external/bazel/leveldb.BUILD b/external/bazel/leveldb.BUILD deleted file mode 100644 index 9b0f56f5d6..0000000000 --- a/external/bazel/leveldb.BUILD +++ /dev/null @@ -1,98 +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. -# - -package(default_visibility = ["//visibility:public"]) - - -config_setting( - name = "darwin", - values = {"cpu": "darwin"}, - visibility = ["//visibility:public"], -) - -SOURCES = ["db/builder.cc", - "db/c.cc", - "db/dbformat.cc", - "db/db_impl.cc", - "db/db_iter.cc", - "db/dumpfile.cc", - "db/filename.cc", - "db/log_reader.cc", - "db/log_writer.cc", - "db/memtable.cc", - "db/repair.cc", - "db/table_cache.cc", - "db/version_edit.cc", - "db/version_set.cc", - "db/write_batch.cc", - "table/block_builder.cc", - "table/block.cc", - "table/filter_block.cc", - "table/format.cc", - "table/iterator.cc", - "table/merger.cc", - "table/table_builder.cc", - "table/table.cc", - "table/two_level_iterator.cc", - "util/arena.cc", - "util/bloom.cc", - "util/cache.cc", - "util/coding.cc", - "util/comparator.cc", - "util/crc32c.cc", - "util/env.cc", - "util/env_posix.cc", - "util/filter_policy.cc", - "util/hash.cc", - "util/histogram.cc", - "util/logging.cc", - "util/options.cc", - "util/status.cc", - "port/port_posix.cc", - "port/port_posix_sse.cc", - "helpers/memenv/memenv.cc", - ] - -cc_library( - name = "leveldb", - srcs = SOURCES, - hdrs = glob([ - "helpers/memenv/*.h", - "util/*.h", - "port/*.h", - "port/win/*.h", - "table/*.h", - "db/*.h", - "include/leveldb/*.h" - ], - exclude = [ - "**/*test.*", - ]), - includes = [ - "include/", - ], - copts = [ - "-fno-builtin-memcmp", - "-DLEVELDB_PLATFORM_POSIX=1", - "-DLEVELDB_ATOMIC_PRESENT", - ], - defines = [ - "LEVELDB_PLATFORM_POSIX", - ] + select({ - ":darwin": ["OS_MACOSX"], - "//conditions:default": [], - }), -) diff --git a/external/bazel/etcdclient.BUILD b/thirdparties/etcdclient.BUILD similarity index 100% rename from external/bazel/etcdclient.BUILD rename to thirdparties/etcdclient.BUILD diff --git a/external/bazel/gmock.BUILD b/thirdparties/gmock.BUILD similarity index 100% rename from external/bazel/gmock.BUILD rename to thirdparties/gmock.BUILD diff --git a/external/bazel/jsoncpp.BUILD b/thirdparties/jsoncpp.BUILD similarity index 100% rename from external/bazel/jsoncpp.BUILD rename to thirdparties/jsoncpp.BUILD diff --git a/external/bazel/rocksdb.BUILD b/thirdparties/rocksdb.BUILD similarity index 100% rename from external/bazel/rocksdb.BUILD rename to thirdparties/rocksdb.BUILD From 22e4510edc51edbba7baa6f24e7b8146723b6e32 Mon Sep 17 00:00:00 2001 From: Hanqing Wu Date: Wed, 13 Apr 2022 11:11:14 +0800 Subject: [PATCH 2/2] docs: add vscode clangd configurations --- ...pport-generate-compile_commands.json.patch | 414 ++++++++++++++++++ README.md | 184 +++----- README_en.md | 150 +++++++ docs/images/clangd/clangd_error.png | Bin 0 -> 31038 bytes 4 files changed, 614 insertions(+), 134 deletions(-) create mode 100644 0001-support-generate-compile_commands.json.patch create mode 100644 README_en.md create mode 100644 docs/images/clangd/clangd_error.png diff --git a/0001-support-generate-compile_commands.json.patch b/0001-support-generate-compile_commands.json.patch new file mode 100644 index 0000000000..fc7ebeebdc --- /dev/null +++ b/0001-support-generate-compile_commands.json.patch @@ -0,0 +1,414 @@ +From 04701122f73b683f08c8f6243f66a65ad99095b7 Mon Sep 17 00:00:00 2001 +From: Hanqing Wu +Date: Wed, 13 Apr 2022 10:40:15 +0800 +Subject: [PATCH] support generate compile_commands.json + +--- + .gitignore | 5 + + WORKSPACE | 27 +++-- + external/bazel/gflags.BUILD | 34 ------- + external/bazel/glog.BUILD | 98 ------------------- + external/bazel/gtest.BUILD | 30 ------ + external/bazel/leveldb.BUILD | 98 ------------------- + .../bazel => thirdparties}/etcdclient.BUILD | 0 + {external/bazel => thirdparties}/gmock.BUILD | 0 + .../bazel => thirdparties}/jsoncpp.BUILD | 0 + .../bazel => thirdparties}/rocksdb.BUILD | 0 + 10 files changed, 25 insertions(+), 267 deletions(-) + delete mode 100644 external/bazel/gflags.BUILD + delete mode 100644 external/bazel/glog.BUILD + delete mode 100644 external/bazel/gtest.BUILD + delete mode 100644 external/bazel/leveldb.BUILD + rename {external/bazel => thirdparties}/etcdclient.BUILD (100%) + rename {external/bazel => thirdparties}/gmock.BUILD (100%) + rename {external/bazel => thirdparties}/jsoncpp.BUILD (100%) + rename {external/bazel => thirdparties}/rocksdb.BUILD (100%) + +diff --git a/.gitignore b/.gitignore +index 8bde1112..d8b02915 100755 +--- a/.gitignore ++++ b/.gitignore +@@ -109,3 +109,8 @@ __not_found__ + thirdparties/rocksdb/lib/ + thirdparties/rocksdb/include/ + thirdparties/rocksdb/rocksdb/ ++ ++/external ++/bazel-* ++/compile_commands.json ++/.cache/ +diff --git a/WORKSPACE b/WORKSPACE +index eb1d8a5f..625aada6 100644 +--- a/WORKSPACE ++++ b/WORKSPACE +@@ -16,8 +16,7 @@ + + 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:git.bzl", "git_repository", "new_git_repository") + load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + + # skylib +@@ -78,7 +77,7 @@ bind( + #import the gtest files. + new_git_repository( + name = "com_google_googletest", +- build_file = "bazel/gmock.BUILD", ++ build_file = "//:thirdparties/gmock.BUILD", + remote = "https://github.com/google/googletest", + tag = "release-1.8.0", + ) +@@ -117,7 +116,7 @@ bind( + + http_archive( + name = "com_github_google_leveldb", +- build_file = "bazel/leveldb.BUILD", ++ build_file = "@com_github_apache_brpc//:leveldb.BUILD", + strip_prefix = "leveldb-a53934a3ae1244679f812d998a4f16f2c7f309a6", + urls = ["https://github.com/google/leveldb/archive/a53934a3ae1244679f812d998a4f16f2c7f309a6.tar.gz"], + ) +@@ -158,7 +157,7 @@ bind( + # jsoncpp + new_git_repository( + name = "jsoncpp", +- build_file = "bazel/jsoncpp.BUILD", ++ build_file = "//:thirdparties/jsoncpp.BUILD", + remote = "https://github.com/open-source-parsers/jsoncpp.git", + tag = "1.8.4", + ) +@@ -170,7 +169,7 @@ bind( + + new_local_repository( + name = "etcdclient", +- build_file = "external/bazel/etcdclient.BUILD", ++ build_file = "//:thirdparties/etcdclient.BUILD", + path = "thirdparties/etcdclient", + ) + +@@ -233,6 +232,20 @@ http_archive( + # RocksDB + new_local_repository( + name = "rocksdb", +- build_file = "external/bazel/rocksdb.BUILD", ++ build_file = "//:thirdparties/rocksdb.BUILD", + path = "thirdparties/rocksdb", + ) ++ ++# Hedron's Compile Commands Extractor for Bazel ++# https://github.com/hedronvision/bazel-compile-commands-extractor ++http_archive( ++ name = "hedron_compile_commands", ++ ++ # Replace the commit hash in both places (below) with the latest, rather than using the stale one here. ++ # Even better, set up Renovate and let it do the work for you (see "Suggestion: Updates" in the README). ++ url = "https://github.com/hedronvision/bazel-compile-commands-extractor/archive/af9af15f7bc16fc3e407e2231abfcb62907d258f.tar.gz", ++ strip_prefix = "bazel-compile-commands-extractor-af9af15f7bc16fc3e407e2231abfcb62907d258f", ++ # When you first run this tool, it'll recommend a sha256 hash to put here with a message like: "DEBUG: Rule 'hedron_compile_commands' indicated that a canonical reproducible form can be obtained by modifying arguments sha256 = ..." ++) ++load("@hedron_compile_commands//:workspace_setup.bzl", "hedron_compile_commands_setup") ++hedron_compile_commands_setup() +diff --git a/external/bazel/gflags.BUILD b/external/bazel/gflags.BUILD +deleted file mode 100644 +index de6d2d02..00000000 +--- a/external/bazel/gflags.BUILD ++++ /dev/null +@@ -1,34 +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. +-# +- +-# Bazel (http://bazel.io/) BUILD file for gflags. +-# +-# See INSTALL.md for instructions for adding gflags to a Bazel workspace. +- +-licenses(["notice"]) +- +-exports_files(["src/gflags_completions.sh", "COPYING.txt"]) +- +-config_setting( +- name = "x64_windows", +- values = {"cpu": "x64_windows"}, +-) +- +-load(":bazel/gflags.bzl", "gflags_sources", "gflags_library") +- +-(hdrs, srcs) = gflags_sources(namespace=["gflags", "google"]) +-gflags_library(hdrs=hdrs, srcs=srcs, threads=0) +-gflags_library(hdrs=hdrs, srcs=srcs, threads=1) +diff --git a/external/bazel/glog.BUILD b/external/bazel/glog.BUILD +deleted file mode 100644 +index 77d88ea7..00000000 +--- a/external/bazel/glog.BUILD ++++ /dev/null +@@ -1,98 +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. +-# +- +-cc_library( +- name = "glog", +- srcs = [ +- "config.h", +- "src/base/commandlineflags.h", +- "src/base/googleinit.h", +- "src/base/mutex.h", +- "src/demangle.cc", +- "src/demangle.h", +- "src/logging.cc", +- "src/raw_logging.cc", +- "src/signalhandler.cc", +- "src/symbolize.cc", +- "src/symbolize.h", +- "src/utilities.cc", +- "src/utilities.h", +- "src/vlog_is_on.cc", +- ] + glob(["src/stacktrace*.h"]), +- hdrs = [ +- "src/glog/log_severity.h", +- "src/glog/logging.h", +- "src/glog/raw_logging.h", +- "src/glog/stl_logging.h", +- "src/glog/vlog_is_on.h", +- ], +- copts = [ +- "-Wno-sign-compare", +- "-U_XOPEN_SOURCE", +- ], +- includes = ["./src"], +- linkopts = ["-lpthread"] + select({ +- ":libunwind": ["-lunwind"], +- "//conditions:default": [], +- }), +- visibility = ["//visibility:public"], +- deps = [ +- "@com_github_gflags_gflags//:gflags", +- ], +-) +- +-config_setting( +- name = "libunwind", +- values = { +- "define": "libunwind=true", +- }, +-) +- +-genrule( +- name = "run_configure", +- srcs = [ +- "README", +- "Makefile.in", +- "config.guess", +- "config.sub", +- "install-sh", +- "ltmain.sh", +- "missing", +- "libglog.pc.in", +- "src/config.h.in", +- "src/glog/logging.h.in", +- "src/glog/raw_logging.h.in", +- "src/glog/stl_logging.h.in", +- "src/glog/vlog_is_on.h.in", +- ], +- outs = [ +- "config.h", +- "src/glog/logging.h", +- "src/glog/raw_logging.h", +- "src/glog/stl_logging.h", +- "src/glog/vlog_is_on.h", +- ], +- tools = [ +- "configure", +- ], +- cmd = "$(location :configure)" + +- "&& cp -v src/config.h $(location config.h) " + +- "&& cp -v src/glog/logging.h $(location src/glog/logging.h) " + +- "&& cp -v src/glog/raw_logging.h $(location src/glog/raw_logging.h) " + +- "&& cp -v src/glog/stl_logging.h $(location src/glog/stl_logging.h) " + +- "&& cp -v src/glog/vlog_is_on.h $(location src/glog/vlog_is_on.h) " +- , +-) +diff --git a/external/bazel/gtest.BUILD b/external/bazel/gtest.BUILD +deleted file mode 100644 +index f88075d5..00000000 +--- a/external/bazel/gtest.BUILD ++++ /dev/null +@@ -1,30 +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. +-# +- +-cc_library( +- name = "main", +- srcs = glob( +- ["src/*.cc"], +- exclude = ["src/gtest-all.cc"] +- ), +- hdrs = glob([ +- "include/**/*.h", +- "src/*.h" +- ]), +- copts = ["-Iexternal/gtest/include"], +- linkopts = ["-pthread"], +- visibility = ["//visibility:public"], +-) +diff --git a/external/bazel/leveldb.BUILD b/external/bazel/leveldb.BUILD +deleted file mode 100644 +index 9b0f56f5..00000000 +--- a/external/bazel/leveldb.BUILD ++++ /dev/null +@@ -1,98 +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. +-# +- +-package(default_visibility = ["//visibility:public"]) +- +- +-config_setting( +- name = "darwin", +- values = {"cpu": "darwin"}, +- visibility = ["//visibility:public"], +-) +- +-SOURCES = ["db/builder.cc", +- "db/c.cc", +- "db/dbformat.cc", +- "db/db_impl.cc", +- "db/db_iter.cc", +- "db/dumpfile.cc", +- "db/filename.cc", +- "db/log_reader.cc", +- "db/log_writer.cc", +- "db/memtable.cc", +- "db/repair.cc", +- "db/table_cache.cc", +- "db/version_edit.cc", +- "db/version_set.cc", +- "db/write_batch.cc", +- "table/block_builder.cc", +- "table/block.cc", +- "table/filter_block.cc", +- "table/format.cc", +- "table/iterator.cc", +- "table/merger.cc", +- "table/table_builder.cc", +- "table/table.cc", +- "table/two_level_iterator.cc", +- "util/arena.cc", +- "util/bloom.cc", +- "util/cache.cc", +- "util/coding.cc", +- "util/comparator.cc", +- "util/crc32c.cc", +- "util/env.cc", +- "util/env_posix.cc", +- "util/filter_policy.cc", +- "util/hash.cc", +- "util/histogram.cc", +- "util/logging.cc", +- "util/options.cc", +- "util/status.cc", +- "port/port_posix.cc", +- "port/port_posix_sse.cc", +- "helpers/memenv/memenv.cc", +- ] +- +-cc_library( +- name = "leveldb", +- srcs = SOURCES, +- hdrs = glob([ +- "helpers/memenv/*.h", +- "util/*.h", +- "port/*.h", +- "port/win/*.h", +- "table/*.h", +- "db/*.h", +- "include/leveldb/*.h" +- ], +- exclude = [ +- "**/*test.*", +- ]), +- includes = [ +- "include/", +- ], +- copts = [ +- "-fno-builtin-memcmp", +- "-DLEVELDB_PLATFORM_POSIX=1", +- "-DLEVELDB_ATOMIC_PRESENT", +- ], +- defines = [ +- "LEVELDB_PLATFORM_POSIX", +- ] + select({ +- ":darwin": ["OS_MACOSX"], +- "//conditions:default": [], +- }), +-) +diff --git a/external/bazel/etcdclient.BUILD b/thirdparties/etcdclient.BUILD +similarity index 100% +rename from external/bazel/etcdclient.BUILD +rename to thirdparties/etcdclient.BUILD +diff --git a/external/bazel/gmock.BUILD b/thirdparties/gmock.BUILD +similarity index 100% +rename from external/bazel/gmock.BUILD +rename to thirdparties/gmock.BUILD +diff --git a/external/bazel/jsoncpp.BUILD b/thirdparties/jsoncpp.BUILD +similarity index 100% +rename from external/bazel/jsoncpp.BUILD +rename to thirdparties/jsoncpp.BUILD +diff --git a/external/bazel/rocksdb.BUILD b/thirdparties/rocksdb.BUILD +similarity index 100% +rename from external/bazel/rocksdb.BUILD +rename to thirdparties/rocksdb.BUILD +-- +2.34.0 + diff --git a/README.md b/README.md index aecf3c1007..e3fd42abdd 100644 --- a/README.md +++ b/README.md @@ -1,150 +1,66 @@ -[中文版](README_cn.md) +## 生成compile_commands.json +1. 应用patch,`git am < 0001-support-generate-compile_commands.json.patch`(这个类似于cherry-pick,会把patch合入) - + 或者 `patch -p1 < 0001-support-generate-compile_commands.json.patch` -# CURVE +2. 清楚之前的编译缓存,`bazel clean` +3. 编译整个项目,`bazel build //...` +4. 生成compile_commands.json,`bazel run @hedron_compile_commands//:refresh_all` (更多使用方式可以参考https://github.com/hedronvision/bazel-compile-commands-extractor) -[![Docs](https://img.shields.io/badge/docs-latest-green.svg)](https://github.com/opencurve/curve/tree/master/docs) -[![Releases](https://img.shields.io/github/v/release/opencurve/curve?include_prereleases)](https://github.com/opencurve/curve/releases) -[![LICENSE](https://img.shields.io/badge/licence-Apache--2.0%2FGPL-blue)](https://github.com/opencurve/curve/blob/master/LICENSE) + 过程中可能会有如下报错: -Curve is a distributed storage system designed and developed by NetEase, featured with high performance, easy operation and cloud native. Curve is compose of CurveBS(Curve Block Storage) and CurveFS(Curve FileSystem). CurveBS supports snapshot, clone, and recover, also supports virtual machines with qemu and physical machine with nbd. CurveFS supports POSIX based on Fuse. + ![](docs/images/clangd/clangd_error.png) -## Curve Architecture -The architecture overview of Curve is as follows: + 需要把之前手动生成的pb.h/cc文件删除(proto目录、curvefs/proto目录下) + + 如果没有其他问题,会在工程目录下生成compile_command.json文件 - +## vscode clangd 配置 -Curve supports deployment in private cloud and public cloud environment, and can also be used in hybrid cloud. The deployment architecture in private cloud environment is as follows: +1. 卸载或禁用ms-vscode.cpptools +2. 搜索clangd并安装 +3. 在设置中,对clangd.arguments加入如下参数 + + ```json + "clangd.arguments": [ + "-j=4", + "--background-index", + "--all-scopes-completion", + "--pch-storage=disk", + "--completion-style=detailed", + "--header-insertion=iwyu", + "--malloc-trim", + "--query-driver=/usr/bin/clang++-11" + ] + ``` - +4. 第一次需要手动启动clangd -The CurveFS shared file storage system can be elastically scaled to public cloud storage, which can provide users with greater capacity elasticity, lower costs, and better performance experience: + 按F1打开命令面板,选择 `clangd: Manually activate extension` - +5. 【可选】可以在工程目录下新建.clangd文件(或者放到 `~/.config/clangd/config.yaml`),开启更多的检查和提示 -## Curve Block Service vs Ceph Block Device + ``` + Diagnostics: + ClangTidy: + Add: [performance-*, modernize-*, readability-*,bugprone-*,] + Remove: [modernize-use-trailing-return-type] + CheckOptions: + readability-identifier-naming.VariableCase: camelBack + UnusedIncludes: Strict + + # 下面几个可以设置为True,可以在对应的地方显示函数形参名称和auto推导出的类型 + InlayHints: + Enabled: False + ParameterNames: False + DeducedTypes: False + ``` -Curve: v1.2.0 +### clangd 官网 -Ceph: L/N -### Performance -Curve random read and write performance far exceeds Ceph in the block storage scenario. +https://clangd.llvm.org/installation -Environment:3 replicas on a 6-node cluster, each node has 20xSATA SSD, 2xE5-2660 v4 and 256GB memory. +### clangd 配置说明 -Single Vol: - - -Multi Vols: - - -### Stability -The stability of the common abnormal Curve is better than that of Ceph in the block storage scenario. -| Fault Case | One Disk Failure | Slow Disk Detect | One Server Failure | Server Suspend Animation | -| :----: | :----: | :----: | :----: | :----: | -| Ceph | jitter 7s | Continuous io jitter | jitter 7s | unrecoverable | -| Curve | jitter 4s | no effect | jitter 4s | jitter 4s | -### Ops -Curve ops is more friendly than Curve in the block storage scenario. -| Ops scenarios | Upgrade clients | Balance | -| :----: | :----: | :----: | -| Ceph | do not support live upgrade | via plug-in with IO influence | -| Curve | support live upgrade with second jitter | auto with no influence on IO | - -## Design Documentation - -- Wanna have a glance at Curve? Click here for [Intro to Curve](https://www.opencurve.io/)! -- Want more details about CurveBS? Our documentation for every component: - - [NEBD](docs/en/nebd_en.md) - - [MDS](docs/en/mds_en.md) - - [Chunkserver](docs/en/chunkserver_design_en.md) - - [Snapshotcloneserver](docs/en/snapshotcloneserver_en.md) - - [CURVE quality control](docs/en/quality_en.md) - - [CURVE monitoring](docs/en/monitor_en.md) - - [Client](docs/en/client_en.md) - - [Client Python API](docs/en/curve-client-python-api_en.md) -- Application based on CurveBS - - [Work with k8s](docs/en/k8s_csi_interface_en.md) -- Want more details about CurveFS? Our documentation for every component(Chinese version only, English version will be uploaded soon): - - [Architecture design](docs/cn/curvefs_architecture.md) - - [Client design](docs/cn/curvefs-client-design.md) - - [Metadata management](docs/cn/curvefs-metaserver-overview.md) - - [Data caching](https://github.com/opencurve/curve-meetup-slides/blob/main/CurveFS/Curve%E6%94%AF%E6%8C%81S3%20%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98%E6%96%B9%E6%A1%88.pdf) - - [Space allocation](https://github.com/opencurve/curve-meetup-slides/blob/main/CurveFS/Curve%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E7%A9%BA%E9%97%B4%E5%88%86%E9%85%8D%E6%96%B9%E6%A1%88.pdf) - - [more details](https://github.com/opencurve/curve-meetup-slides/tree/main/CurveFS) - -## Quick Start of CurveBS - -In order to improve the operation and maintenance convenience of Curve, we designed and developed the [CurveAdm](https://github.com/opencurve/curveadm) project, which is mainly used for deploying and managing Curve clusters. Currently, it supports the deployment of CurveBS & CurveFS (scaleout, upgrade and other functions are under development), please refer to the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki) for related documentation, and install the CurveAdm tool according to the manual before deploying the Curve cluster. - -### Deploy an all-in-one environment (to try how CURVE works) -Please refer to the CurveBS cluster deployment steps in the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki/curvebs-cluster-deployment) , for the single-machine experience environment, please use the template about "cluster topology file for single-machine deployment". - - -[Deploy on single machine - deprecated method](docs/en/deploy_en.md#deploy-on-single-machine) - -### Deploy multi-machine cluster (try it in production environment) -Please refer to the CurveBS cluster deployment steps in the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki/curvebs-cluster-deployment) , please use the template about "cluster topology file for multi-machine deployment". - - -[Deploy on multiple machines - deprecated method](docs/en/deploy_en.md#deploy-on-multiple-machines) - -### curve_ops_tool introduction - -[curve_ops_tool introduction](docs/en/curve_ops_tool_en.md) - -## Quick Start of CurveFS -In order to improve the operation and maintenance convenience of Curve, we designed and developed the [CurveAdm](https://github.com/opencurve/curveadm) project, which is mainly used for deploying and managing Curve clusters. Currently, it supports the deployment of CurveBS & CurveFS (scaleout, upgrade and other functions are under development), please refer to the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki) for related documentation, and install the CurveAdm tool according to the manual before deploying the Curve cluster. - -Detail for deploying CurveFS cluster: [CurveFS ​​deployment](https://github.com/opencurve/curveadm/wiki/curvefs-cluster-deployment) - -### curvefs_tool introduction - -[curvefs_tool introduction](curvefs/src/tools#readme) - - -## For Developers - -### Deploy build and development environment - -[development environment deployment](docs/en/build_and_run_en.md) - -### Compile test cases and run -[test cases compiling and running](docs/en/build_and_run_en.md#test-case-compilation-and-execution) - -### FIO curve block storage engine -Fio curve engine is added, you can clone https://github.com/opencurve/fio and compile the fio tool with our engine(depend on nebd lib), fio command line example: `./fio --thread --rw=randwrite --bs=4k --ioengine=nebd --nebd=cbd:pool//pfstest_test_ --iodepth=10 --runtime=120 --numjobs=10 --time_based --group_reporting --name=curve-fio-test` - -### Coding style guides -CURVE is coded following [Google C++ Style Guide strictly](https://google.github.io/styleguide/cppguide.html). Please follow this guideline if you're trying to contribute your codes. - -### Code coverage requirement -1. Unit tests: Incremental line coverage ≥ 80%, incremental branch coverage ≥ 70% -2. Integration tests: Measure together with unit tests, and should fulfill the same requirement -3. Exception tests: Not required yet - -### Other processes - -After finishing the development of your code, you should submit a pull request to master branch of CURVE and fill out a pull request template. The pull request will trigger the CI automatically, and the code will only be merged after passing the CI and being reviewed. The Jenkins username and password of CI is netease/netease. If the CI fails to run, you can login to the Jenkins platform to view the reason for the failure. - -For more detail, please refer to [CONTRIBUTING](https://github.com/opencurve/curve/blob/master/CONTRIBUTING.md). - -## Release Cycle -- CURVE release cycle:Half a year for major version, 1~2 months for minor version - -- Versioning format: We use a sequence of three digits and a suffix (x.y.z{-suffix}), x is the major version, y is the minor version, and z is for bugfix. The suffix is for distinguishing beta (-beta), RC (-rc) and GA version (without any suffix). Major version x will increase 1 every half year, and y will increase every 1~2 months. After a version is released, number z will increase if there's any bugfix. - -## Branch - -All the developments will be done under master branch. If there's any new version to establish, a new branch release-x.y will be pulled from the master, and the new version will be released from this branch. - -## Feedback & Contact - -- [Github Issues](https://github.com/openCURVE/CURVE/issues):You are sincerely welcomed to issue any bugs you came across or any suggestions through Github issues. If you have any question you can refer to our FAQ or join our user group for more details. -- [FAQ](https://github.com/openCURVE/CURVE/wiki/CURVE-FAQ):Frequently asked question in our user group, and we'll keep working on it. -- User group:We use Wechat group currently. -- [Double Week Meetings](https://github.com/opencurve/curve-meetup-slides/tree/main/2022): We have an online community meeting every two weeks which talk about what Curve is doing and planning to do. The time and links of the meeting are public in the user group and [Double Week Meetings](https://github.com/opencurve/curve-meetup-slides/tree/main/2022). - - +https://clangd.llvm.org/config diff --git a/README_en.md b/README_en.md new file mode 100644 index 0000000000..aecf3c1007 --- /dev/null +++ b/README_en.md @@ -0,0 +1,150 @@ +[中文版](README_cn.md) + + + + +# CURVE + +[![Docs](https://img.shields.io/badge/docs-latest-green.svg)](https://github.com/opencurve/curve/tree/master/docs) +[![Releases](https://img.shields.io/github/v/release/opencurve/curve?include_prereleases)](https://github.com/opencurve/curve/releases) +[![LICENSE](https://img.shields.io/badge/licence-Apache--2.0%2FGPL-blue)](https://github.com/opencurve/curve/blob/master/LICENSE) + +Curve is a distributed storage system designed and developed by NetEase, featured with high performance, easy operation and cloud native. Curve is compose of CurveBS(Curve Block Storage) and CurveFS(Curve FileSystem). CurveBS supports snapshot, clone, and recover, also supports virtual machines with qemu and physical machine with nbd. CurveFS supports POSIX based on Fuse. + +## Curve Architecture +The architecture overview of Curve is as follows: + + + +Curve supports deployment in private cloud and public cloud environment, and can also be used in hybrid cloud. The deployment architecture in private cloud environment is as follows: + + + +The CurveFS shared file storage system can be elastically scaled to public cloud storage, which can provide users with greater capacity elasticity, lower costs, and better performance experience: + + + +## Curve Block Service vs Ceph Block Device + +Curve: v1.2.0 + +Ceph: L/N +### Performance +Curve random read and write performance far exceeds Ceph in the block storage scenario. + +Environment:3 replicas on a 6-node cluster, each node has 20xSATA SSD, 2xE5-2660 v4 and 256GB memory. + +Single Vol: + + +Multi Vols: + + +### Stability +The stability of the common abnormal Curve is better than that of Ceph in the block storage scenario. +| Fault Case | One Disk Failure | Slow Disk Detect | One Server Failure | Server Suspend Animation | +| :----: | :----: | :----: | :----: | :----: | +| Ceph | jitter 7s | Continuous io jitter | jitter 7s | unrecoverable | +| Curve | jitter 4s | no effect | jitter 4s | jitter 4s | +### Ops +Curve ops is more friendly than Curve in the block storage scenario. +| Ops scenarios | Upgrade clients | Balance | +| :----: | :----: | :----: | +| Ceph | do not support live upgrade | via plug-in with IO influence | +| Curve | support live upgrade with second jitter | auto with no influence on IO | + +## Design Documentation + +- Wanna have a glance at Curve? Click here for [Intro to Curve](https://www.opencurve.io/)! +- Want more details about CurveBS? Our documentation for every component: + - [NEBD](docs/en/nebd_en.md) + - [MDS](docs/en/mds_en.md) + - [Chunkserver](docs/en/chunkserver_design_en.md) + - [Snapshotcloneserver](docs/en/snapshotcloneserver_en.md) + - [CURVE quality control](docs/en/quality_en.md) + - [CURVE monitoring](docs/en/monitor_en.md) + - [Client](docs/en/client_en.md) + - [Client Python API](docs/en/curve-client-python-api_en.md) +- Application based on CurveBS + - [Work with k8s](docs/en/k8s_csi_interface_en.md) +- Want more details about CurveFS? Our documentation for every component(Chinese version only, English version will be uploaded soon): + - [Architecture design](docs/cn/curvefs_architecture.md) + - [Client design](docs/cn/curvefs-client-design.md) + - [Metadata management](docs/cn/curvefs-metaserver-overview.md) + - [Data caching](https://github.com/opencurve/curve-meetup-slides/blob/main/CurveFS/Curve%E6%94%AF%E6%8C%81S3%20%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98%E6%96%B9%E6%A1%88.pdf) + - [Space allocation](https://github.com/opencurve/curve-meetup-slides/blob/main/CurveFS/Curve%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E7%A9%BA%E9%97%B4%E5%88%86%E9%85%8D%E6%96%B9%E6%A1%88.pdf) + - [more details](https://github.com/opencurve/curve-meetup-slides/tree/main/CurveFS) + +## Quick Start of CurveBS + +In order to improve the operation and maintenance convenience of Curve, we designed and developed the [CurveAdm](https://github.com/opencurve/curveadm) project, which is mainly used for deploying and managing Curve clusters. Currently, it supports the deployment of CurveBS & CurveFS (scaleout, upgrade and other functions are under development), please refer to the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki) for related documentation, and install the CurveAdm tool according to the manual before deploying the Curve cluster. + +### Deploy an all-in-one environment (to try how CURVE works) +Please refer to the CurveBS cluster deployment steps in the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki/curvebs-cluster-deployment) , for the single-machine experience environment, please use the template about "cluster topology file for single-machine deployment". + + +[Deploy on single machine - deprecated method](docs/en/deploy_en.md#deploy-on-single-machine) + +### Deploy multi-machine cluster (try it in production environment) +Please refer to the CurveBS cluster deployment steps in the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki/curvebs-cluster-deployment) , please use the template about "cluster topology file for multi-machine deployment". + + +[Deploy on multiple machines - deprecated method](docs/en/deploy_en.md#deploy-on-multiple-machines) + +### curve_ops_tool introduction + +[curve_ops_tool introduction](docs/en/curve_ops_tool_en.md) + +## Quick Start of CurveFS +In order to improve the operation and maintenance convenience of Curve, we designed and developed the [CurveAdm](https://github.com/opencurve/curveadm) project, which is mainly used for deploying and managing Curve clusters. Currently, it supports the deployment of CurveBS & CurveFS (scaleout, upgrade and other functions are under development), please refer to the [CurveAdm User Manual](https://github.com/opencurve/curveadm/wiki) for related documentation, and install the CurveAdm tool according to the manual before deploying the Curve cluster. + +Detail for deploying CurveFS cluster: [CurveFS ​​deployment](https://github.com/opencurve/curveadm/wiki/curvefs-cluster-deployment) + +### curvefs_tool introduction + +[curvefs_tool introduction](curvefs/src/tools#readme) + + +## For Developers + +### Deploy build and development environment + +[development environment deployment](docs/en/build_and_run_en.md) + +### Compile test cases and run +[test cases compiling and running](docs/en/build_and_run_en.md#test-case-compilation-and-execution) + +### FIO curve block storage engine +Fio curve engine is added, you can clone https://github.com/opencurve/fio and compile the fio tool with our engine(depend on nebd lib), fio command line example: `./fio --thread --rw=randwrite --bs=4k --ioengine=nebd --nebd=cbd:pool//pfstest_test_ --iodepth=10 --runtime=120 --numjobs=10 --time_based --group_reporting --name=curve-fio-test` + +### Coding style guides +CURVE is coded following [Google C++ Style Guide strictly](https://google.github.io/styleguide/cppguide.html). Please follow this guideline if you're trying to contribute your codes. + +### Code coverage requirement +1. Unit tests: Incremental line coverage ≥ 80%, incremental branch coverage ≥ 70% +2. Integration tests: Measure together with unit tests, and should fulfill the same requirement +3. Exception tests: Not required yet + +### Other processes + +After finishing the development of your code, you should submit a pull request to master branch of CURVE and fill out a pull request template. The pull request will trigger the CI automatically, and the code will only be merged after passing the CI and being reviewed. The Jenkins username and password of CI is netease/netease. If the CI fails to run, you can login to the Jenkins platform to view the reason for the failure. + +For more detail, please refer to [CONTRIBUTING](https://github.com/opencurve/curve/blob/master/CONTRIBUTING.md). + +## Release Cycle +- CURVE release cycle:Half a year for major version, 1~2 months for minor version + +- Versioning format: We use a sequence of three digits and a suffix (x.y.z{-suffix}), x is the major version, y is the minor version, and z is for bugfix. The suffix is for distinguishing beta (-beta), RC (-rc) and GA version (without any suffix). Major version x will increase 1 every half year, and y will increase every 1~2 months. After a version is released, number z will increase if there's any bugfix. + +## Branch + +All the developments will be done under master branch. If there's any new version to establish, a new branch release-x.y will be pulled from the master, and the new version will be released from this branch. + +## Feedback & Contact + +- [Github Issues](https://github.com/openCURVE/CURVE/issues):You are sincerely welcomed to issue any bugs you came across or any suggestions through Github issues. If you have any question you can refer to our FAQ or join our user group for more details. +- [FAQ](https://github.com/openCURVE/CURVE/wiki/CURVE-FAQ):Frequently asked question in our user group, and we'll keep working on it. +- User group:We use Wechat group currently. +- [Double Week Meetings](https://github.com/opencurve/curve-meetup-slides/tree/main/2022): We have an online community meeting every two weeks which talk about what Curve is doing and planning to do. The time and links of the meeting are public in the user group and [Double Week Meetings](https://github.com/opencurve/curve-meetup-slides/tree/main/2022). + + diff --git a/docs/images/clangd/clangd_error.png b/docs/images/clangd/clangd_error.png new file mode 100644 index 0000000000000000000000000000000000000000..c725a35b3f4a7b9eb6dbbc4dbf5a89d779fdf0c9 GIT binary patch literal 31038 zcmcG#XFyZw);1i689XzBj-&K8BMOcv2r(diX3*fMfG7|tA<_~h6oF6^${a^}5fSM` zje^tw5tNQX=nxS@2rbe}0wF{aLMZPJ&N=64=Y5|a-?#q|Aban-thKInU2ENO*DTE? zzmxwC1OiF^e(Az>5J;>A1lkw)H*w%E>X!E~z>j?a*Uf(emG>(y0>6BX`qkoB5U4Wc zz?RE5!0+GQy<{H%0{sAd@dwPl38YF02oy5-`-NX^LY$ZL7DH9_iBMll%gb@+W!0z7 zDz>_xg)L;g-mfBmyyb^#yvqEdUEKY=(=BUjk&)Z$GzRcQ(M3EccJ|AshHoTVzIVdIAeiqHgg+w;x^R{M2cbrLkgQ;QtR6~L)uT8OU=^C0?tCd`(A;a%oESWjx zzquLuo#8$Z=o93P5L60X77ofk5o8ztzPYg#k+pA_G^$09q_{ju$B5PaZ0{PUywYDGa`O;t zXWJ_oXGcxJIZ5SghZ260^|lS-ech{r^}<)hm7eTjVcp}@<;q@u`pCjZT>7Atv%ZWf zMjD4_8V=4{mzqahJno3?U=!cy>I|lnn@3Q<%B{*O%14#yb1eSMu37omQcK2lCw87{pCI}8?8 zu1v&1OjNmzjtX_bf$X;2pwM-v#0Q#Mqw{Zx>5_D;oSJX}Wb^^DX3r#P*#V~0GJQ7$ zG(r8EEbh^ELK0Ch{ed_{!Ps)LB#+B!L|lZ^8?7VNO_cOCde_RKIzwqIa0C9@Q1Y@7Nt3a`o#fbZ z&B(^J@oQHbC1z2gQyO%|`jmh`2 z2tH)DZdCtR+ksY;)ZfT+U}}~X!YJg#^74b-DYMfsn(@ZVZLNNNb)|A`fzhL*fN^!!vbO)<)XSDNpU zFr|<)o9wNz4kn>sN?}!yJbBW3UL&~fvG!Wy4FwGdV)j*Q$-FBRMmv03+}7mLV7X@5 zt_kgzR|88i`(y$4tqf&aMQOQ+UJA#Pt>J_Qcd?e!z^dC95c_Pt0Xo_SIRkrZZYY@^+=;CgcY+z z{0H!$N2hw1-0XOV`iKaUUaN0^Eejf|c)R%UElMv1NjVdWVoYied@`1=5yk!>z<8Zv zO(r?`q46|x(){BF5_>gsAXZ%jY~?dDho`oh$G`~U!-Pvb{>yy;Fu8!D>z}kQr0<@Kh1d|+4kVYSif(+t z!{H)K+s-~gG*z$V#NdnU;<%9}6T$=1l-z{a*=S%SpNww-_ulGjFA1Mw(gz+G|4`3e zzs;e$SV1Jl;%yQ6WxzdLiI&%{=3c>H@W&LNoMLih=5CH43F7ztOIf(_tY32zt>!jj?|ja zLmx!d#`aF#=vo|#9$E@_dz5lzZB|ZFtUG2!h3cGspy!WqVR#d*<5Fl1Kk$rdNlYp` z?>vlmAvBE9>AK#2K2m;P)M5NeRO|5x-W3V&qRVxl_d5G0ab2=?^Z z#v)UkJD^?HNGA{_8*Mj#xAb~<0!EY^Bo2od%YpTSmYMD*+jPa`sln76g7QGyT;q(H z9a5A}xt zz#~f~(ayM=@tmW(kbsqiC;|i4Y>RFo%pKDO*Qp=$f2X(L`Mq~i`4z;_FUxJLUiqfd zZ>vMfwQ;~aRqCXAt9FMG@O0&wf%Injzl7k zJ#_Px`p8(^WPQ7R1Po;}cO{YTDPi7VrU}Ia3Yh8aXxAl=lg;_E2LPv6mT0*vQ#EJ4 zF{jmpa+kdSz=_dWRCJwmy{q|8dsSVoy*v6@Z}N7Ql5>#PIb-`)0}{N>Ks%2Nc>6R~ zz26l{iC3InIQzcuVxcaSrh{Z^#szo;%)qC|^a%$15p)@o^;V9UpCAW^D?L)_=^z@Z zMT8waWFjRFdLt=%H!{hNitCu8xcQgGy`h1;s>~w-v&oi6hN>CN8xqG`^?Kz7`t6$} zx@g-3sE@P?;o%^s@d(QAPLomIIz8J*vraPX^&PxmB98k~ts%wSO=sG6sv!WRTZg^d z{-1E>O5i@wFOp(s$L?Emy=?k|A)uTwtVGKP@TTW(FKXbF)@A87Vm2e4%q7`;;1BmiqskWJlXQ4@G^v6eF-E zmv;NLe?c8mX-N-)$dXaj&$niwbOA5c7Fn2kU-bErb2(Rc<4{zmpd2HYwdJOPMq4v= z!>K|YWXjCN(a$3{1_@q3_{c>9%$ynT&h$B_1BJwTG zOdSThEw+ZZ@@@ z{%63PAe!3b3zkN$tvI_*N5Enb! za(_YNGriDZHG~s7k6Zqnw=YBj^%d(kyu*zv0G5crCdxxLYF~LwQ|!CfCSoAgUWW77 z1r%`*YKl^j+uqUzfm%v{U<;rNaQ!=u)jIy(_w`50lf3?|b#8ijICP64=$(kv4HAWM zuBRXjscbA$AF-2#CjjvE##m%?A3rs%;e#sXc(xIhy^u8kENTmkH!oh;(xoZeYbyU7 zT`x|9`vWh1atQE=Z_r!L%SRBD5=o;yV5zME9uf|%40|qXG6LEXcvoia+Rb|%pH*nQaUOlx-EKfolw8!HL!6^>qQN=frd zm)Lb~@Ev+d@jskJE_^sxCRs)mwx3kVG6vGjgr{T+8W@-SNUt%2TybRnRN?DVd^%3f zUb9Y{wKQ@VwH(7HIW=o0&=aNftBSBezt`aSoH#U)ElhkXe(Q~#-;Z%G7uT5>i=@hI z(=txdGkFgoSzrE^WnqA-uOvs{ENt$o4^n+8ZYcc5#IyGcXcSPdO*0j??QyQ9$JGzY zJS?F_FT%VU@)NTZ>v@4X_#Lm0=78rE;b?WI`ty79eYS11KSIhBBrn-F^zPRx1kyX> z*TpK>@xF}AWu-+0as@%7z32Q7DDI6q_Y&fPaaiRs^PRxJOfOOL5oIb`$M18%De{fO z3rqRKu?HBe;?x>Qoo4t$JcMp|))1D1O(mbu-Lb{7oQ08IL4=*Fw39V-hXGEHTUBy< z;k57|_Bf#!?;}w%dB#k4AwL=d9#+KL1vD;j}It zJo=*K$e=wy77Ut#r%pq8m?hMSXmGQ68@6}@vs~-3UCOFH1*Hl#>WoVKbPa^BS~c~f zJ%?DjRbwHK%tQzg6?{*WwRl}BlD9X_ZR1}phhX^f0MFQb7!d(A8#jlRQ(XWP${UZO9T&=l0c|w z_-=1y%`Q_rle0Y{8^J9$7NHk(%!9Cb9Am=h6LUeGRgxDiLg3BMauN{vFq5D2{xe1( zc^iD>`e4%JOXN1z+7cBNXM$k?tIO)VpGkiI60@8bP@@9%$N1Jn+RZG4Nd*jW&__vG zeZaO-0PSb&KK&Q!ooo_BZ7|aHMKnaWX}rM5bq^z`zx-&prT%*~T{Uz-w^8?FXZi51 zMn5XYgrzqey&i8pKZrktsO;j^zOOz7&@&~5p`R|2hhYNST%a{_F3if`Z319Zti`r# zP7bDUxUF}ry@X+15Lp0oVgJ)y{^Lp)f)Zu z2w8!4!eqQ6oYHjd`(?<~Ha*+A6qox<5%4_}5VUWJ4dGCdnp>>|atzM+;LMcvK+Blm zw{QP4m%Bf0zH;Z4Jz@9$>;HvAGr&}wzo5BvU8%!k&#Uw7Q4ANQO#agS7&1Ma&n0{oXxakHi*m%dS2*OpK) z-H4i&7lggqa2m{KgH=@UTgY)Wg40=0Gaxbn`H7_HmYZ%|Py9xhv-cQ3Td#Zq&Loz@e_Ot5~NgJ_!yq% z=X_)qPAU@UbNx2uBkC&z>N%1?%)X+SU%c_so)Uc~jXizb@kDF03_Az%jO26y31B}4 zZH8WN((X1#QUI;P^|s&Ox&&Tz)`IP!&1$RdUOWSsBBK4JuB%toHoAts&gKTH5EjhU zqy3Ur#qQ2x$(NICs|VH_Z@Bqc)C2`jm@kY8Oc-Ep&$a%lkf_eL~@*_GK`jXOWvXE1Fs!>Ca?Pl4y4y8#&}Pi9MLKhWm>JM3s87@_FQTsp>M*z4xK$yR>!@K65qfoKU;~3=xTLt-0I|lU z*JVHb3DzJYP!wq}7&4O@Wh2>QVq&sF7#Rxe>YY*HG(K~5BVnaz-NEn#cmHRIfyc@0 zl2Db(sf=>iy4!_j^P6W%hXD#g0d(cD`}V4@Mz%ta!_ZfuUUxMF8E4T3hJA<{wQklh zo<8Y8$zJyYWzsd_d71qH8QY@(f5rD)f$_148{|SX1=wy6VxZe2YN7RVUVp82)lVfc zD-&{lU2;;(r8rvkB_}tYxjr(XN!CB9fpUHc7Cq%1B$staS#YgP3=}ml0-N84hGUCE z*OJ_DloP9}V1@cC=WuXgqY3#Jo#TTu?iUPE0-fUseoB+~-7kO>?(sJ{ z`d|@0T{b8?D8Wyyg8@$XEBt3@cVBdW#PDQe`jf2lw;JJ$?QJ;?l#Q)II=jxUE7c-Q zX}JzMfx>JX{GB?$%3a%O;{#?_E5iH-5Zz~<`NhzoneuZP^$+p~)WyO0i-nWS5ntxV zPxeNvc}XhEwgzfYbAW83n^9r_2I6piO+Rb#BPHI{cF;%Hytx?bimMZayt+C&*U++k z!z)T;qmr29GOz&z$qw`+tijQz^gl2;l@odV_+*56k^i{984ynN|1|=rMP~Dax90Y? zl&#xLU^_oCdE&HYotAD<`u5uB3b@wq_D#Wa%wuBWX=z)W&Xh4Q2u>D#nvp}b(u*c! zud^@e=Rr+3-&f8*UMH!_q!PqdPwwB@yq&c8IRe8qA>44|)U6}|&KRzSn!&oGCM3x} z86r+KZ#lr(b0^ZkB=R79KM0ia?LQDJziJP$Y#|wWbG>d~IE~v$!zp#bU!3L|p~iLh zFH*B3FCsOqXn@r8z5I`)Mw?XV2;>Oo!UqZlun!fu&g4QjEA{B951Wfi#h$HThaBo{ zMSmTvtHdBp`d%dSZFw2sS?-y=_DR6HO=Hb1)ejkReKMD8bR8L-E0+rSet%9ad-MgStV|Z5)H4LJOL{(PhsGm!9v=Pv2Z@zvjOsznH?#Vr-5UPPCsgfqDQ| zUq~pqp)lZ^veM&uF6~Utg}EG}Qi(zrC&H!)hC!F!PymqGA8I0}(ZnvU^s(Gt_llw{ zsZXd-4p==}bd#F};`4MXNTOmNdZSAG;Lha0lv$JVet(W^ulOZ}gNFFhrX%vjhGr%} z+?NJ0L*|*4n5H186E^pcFP>jW8)hA`P~gc%?V43S^VtW=2SN=1b9$)H-&RC7veG7l z@A-xUng@V3z>?@{ZwiJxRS!N=9hKt&c9#DC#KlRUg^ZGg`CjMc*NNTDFacO@kEMiG zfme*SO-I36D*1Kt52#OUFFJwhiDn+)9yG&^Xfbg24#C zWQeV9ORnWSbRv74+sKPdo6os5UVj9Fp=+&L4=yvn*v|&&AE>vxX{SuI?H(S9InYH# zw|>^pb+&51nhaEKvaBL?+X)+(8Ji|FTnc4{w0a#;EW4CFl$0$z{a+z4(X(~ta`Hr) zSK~@s1v&-ClyECh<&uYgGS^M%H`q1cLfZY?Pxd>PKiFb5N~9@KbP+c+D!&3a@zcp$eX32U#O$BV{KHAgIpoVbCwjBrWKoVe z9`OibQCO>0s8+L~Sc+Fhx#d;VKO`90F96fOrF@uOG&NW)iltRFq_+I*xe{BeNAzkG z@`^jM^@YCyDvx|TffDaic_sO$(K8d!()5%3m&$-g+KSS>M0p2-=k@KoKQO?xye?{^ z_^mYKwGz*vBulZ8J=x8bR5W+)hvnSao(H&b)6JSrdtBmWKm@bQC3ogqZkM)I430S_ zg7tUu?f-!+iPoBl*4tz!m^N!VS`+MB> z$}%Qu8DW72c>{YZ&?E zU@i;*vdaHGkg1lK)^{M7?G;SnX+(ZE@5-#ZZbt)(BPUs2Gc@DjcQaMB-k|Bup``xr z-JW+m&{V|&t99#}J(nSzsIw^cjhE1}>LYdyLqJ!MNPcN(!c78mIa%ya-)j~$ihTxM zi>|?=cP1AI_9Mk+=;kzb?)8pz$?MAa6l=O@ z;}(`aLO+kjwz{fEYcx^T(&?(tR19Z2eGYS7{HLm|olyGlR05O!K3^ckPU&50>8N-J zu;yz3MF-&O8Y%jRzu+pyQnTu<#KZwfYMz!eK%sg8NO|*pxWRxxcQ|-v52#{%G-ab0 z3gMo8`QLz|ltjg!7PD5+R{m-k0*tm^l(4NX;m_R^+qf*Y^B0O861$6sb(8B4wj3tE{U;{_If;peMS}L| zwW#13^92idtNl}9kgH(~y*}QV`u{-7x;FnSE%SO-vav9lPAV9k5uWd|>sn=#g~%k% zX_-`e+$sI>k@pUbzKLt8bkcQGlB~lR#<+F$otglBExu^7huR0`BV*U&98Y`lIkY{8TExtnJ5()$u1HHAO^ZD%R z-5evvwWW!?m!bU;f27FY+|8#GX!dC@p*NcBIB}H^72z~vkwEABOXGjg=Mw)XeXd9R z+eVdX50eo6JV3apwcQ?O`ZTp^%)TQkEMCV!=Q9!D1Q(>$9QHoOd^<~#PNjaKR-X=w z82edtbXCFoFYxlS%@=q%ZmJL+bSo$*M|cS+kX?XrDzVGEm8prFU^rnIiN4sOmC|J( zk56VBvQiU^0Y51fe=6~xxfSu@0k;ATQXc}QSSMK8aCY%OY6VviJYmwEliN0uDzwhI z1Emd6#U8!0Z&kzHP+)+OeUD}~#RETHv+H9XMoO}KQK@BdI)*${PzaqgH=O-`_+$V7 z23?$gmT@g82}rgtEs-tXa86y$Q|0K);ORc@ywDj`HJ}E6Q5|}t9~Dn>CH(;2G@=g6 zD+nEWqfB;B*;+bB*bC~kLRoi79Q0MdV=c3_z}(YGW{JY{Zz}UZN%L*@xqluo17AwZ$ zw-)8X|E|ro$H>1g->$KgEF`x^Bwz1Cd7z)W)n8+|k?M=VX#jOZGkZlKwsAx9Ff!nC zNu7H89(gP*VN(5{GD*S)1jiWBYAXT55j%O7v)GJOMe@Al}&1OHc(T$-T; z_tH*mv2_mQ71Z2UI)h=c)12h?MXDRySnTdre?h`|xL3ZMN;}L3N+?N`Ugh11QecY} zsil!x-HQ^+12KRKT#66wzdtYlG3;Ok0#OiaAA}U@kIt(y0vk*8{>gma?-g*p0Jy;Y z1sCV~L~!w12<6*Zyky1Vf58WD~sWf_kHYyNaGK{sh4Z7h=yD0o-{?V}lhTuIZI`>hw_!O_3Y)o9AWrDb$& zrTf-T$VPe4I`vZ4<~(}l`mbrgp|5~Qd`s#tkT8(MPv#s`MVDV~FTInjgX)#9=~ut- zPTtiw*vldOo@ZS|e_d|`12>9Q5|*gl2)cq_IM>bzkBoF0O|m+HBJ=HYf!>OxLItxf z4*I!i6Doq~TN$QMvLTx;TB77~SpR)(pc!EQ;aLoqx*q;`&1oQM92yVcF&XLZ-q2$JRo-b;q=RXNh(za$OA#A00yFY0dI+E+Fn%(ef5uj zhkIJ&0TJim9zXds`9-gj|9_$Y@Ic@a^~;G$G`x?D2qQZF&4%DI%|vyFoq=SVD*TJ6 z%(x!pgesP&C$M~V0PIoT6YK7T%$lNIBzymjSf@6sMtl`~D*2;0aI0u=`G-Uc&bu2~ zZG|%?>aMc>A{-44#!hL$3Dn}|w)x7Cf_*nDdv{77MY5%uRS$q#0D2cZNo}s%7KHOS z_vK^9_Y}d={9pwK%}FZHlI-dIJ-%ZqOZ-y`g^g(SR*VALCMv7hHYm`lvxrP(8jpqF zn^zh3+h%DD@qRI-i;e$Pz2Uw6Z`B*|iujc5tWuYA0u#$BTb(T|r^z0y+jG%f8h_dH zweBlBwgLg?&MO6awW6i<;FQknYyY`+LmD|-oNLF?7M=-a%#R5IBYXukWfEgF{Enub zr)syVNv)*nspbnEb8ny<``(PmDD@%}=K1>hA{qD`w)_qv62JVa+BtbvbHb4-4@mmJ z{Pk3IQHPCh1N>#M_2!|)(!)1e-IHR)GY1#PI`ImJfC9Vk8f!vT@^=}CJYD@O`LDJ_ z-2o+woYp_G6$B1s_4dpDu4Wyr^@Nh_PicLToOdwQ)o(m|30E6mMs@{3niI4vl$cS<$6ja z>J1@H61*%P(JM_!tv&e=cl$KG|I$$4ZdDjz=X#!tz0gn?zbBwkx}9^#FT3x|U#-BJ z`#1Dum0Fu<_1$mG7cBo|!rkcY+*xoVS{q@==4Aw+LWErW zlJuV;cxG>l88)H(m;cB!{z%1@o|`SnWThhV#9t16#w_zUkKP;pIx9Ev_WWr?^bB*y zdhlFAignlGM$?De$s#@NvV_|~@ags}#YoC&6S$~&28Xwwl!2xX_GjJllc)MUVk3HJ zC$Z+5TO;<~vTZ13yj&K-*+<<()o`m(Bf?g+Vqn*mXA*S$wpRr;m!bd^fA^H}kGJJ) z2b~}qYBZvpitvvgPuSgWrP@)OrP$b2aME`Kl z>ClGH4P|YCr+gK*q}@EIjo6v<7b03v{)vb}PXG}E<$Hk2)lc02ZRLtKYzR%HXhpKB zOWX$Ys5NDfQ2YKMpk2+=jC}-ex{m4Eif?t-Gl^`d+4kd^@yj+m_&NPAVQgF71N4bF zYc(@nA)3%|Wv}lcL|SB!?uUX?A;;u)e)S3o4SSN4NCzG9=zq}LyJGG3&?V{qYeU`3 zO+V|vO;K=UvpaFvlth0Zk_G#2{@-OmA^tzgf{qH%>fq;A7wX-%5(jSm%rIxOfvO-? zoRig2c#rtjP$c^#wbwQA`icB1 zD;&Mb2z-Mr*hq}%*Zm--{&9atbTUNK)2Deb2kz^J|DQ_!x{ZGWue<^f_x@C z@|*Ik1oPJnWI+NY7)kaJ(2!!RW3f)K*29#BIJ3|DZ|d*ct7$tIf4kfA~H zi4}VyBx(N(->*zfnj@7WpiV?F8@8~0Kt3Zaygp-3S4_qwJU!?-*_?iwt8UVEs`;ar z$Nt7H{?2x;;Cz;E(nSA<=PVq+O_TzeXz{-|^;FKVXjck4`{NThYwx!f}pf1d2EDS5s{>FF! z6T03<&wq47qbPsZ1n0b%7M8jptpb&Uw&VT(%m}{I)GMuJIOV;xkUfjJ2+KHyu+6Qn zJv)iatv8Mn`%|v{2cv? zv5k(j;M19@-UBpv?J6^QsQ5<{w;7mSjt0kiYdbqLtsJ2gG>4g~-!XkB9C*rAeB{NB zd95`Rf0)wRt%X(MzS!(*x<*n(*p>xhJkV7kHg$E1eHoGC_Ntgh1%|8&>Gcw!tynYa zZz3tca07}+8hR^z$Y}gXPT-`%d1FOy3*6b{gY3hkb{qGdwtMw!Ju69vzE)kLV3J%P zmPsi!8>wk1cqK0VF-AA^H=t<_b(*ItxC|uh$J;F7i4|2+SL~85clP zwrVI`YXpjYXfF?yK3AJ%Vt>Tz|4m*{o;8@NmEIrUzpcRwnaWO9ObB&yLp_Wx%oFG! zBQSx#x2J-`(g^~chQ2(=PMD0bDO8)phqA?3dxAadZn->~@krE!Vhkd+UyND5Jne%y zxY>)}_@246zUf}?zOnx{z;C5d0Kbjg`fQ%L4Av*@=f(FaVe9(dcFtLPmky6rcC0<< z;_!O`DO0rkOFGE)8+%hYpX6!W%_q*HA2q7VL@WGmy;@qYkKj|4b|!$tW^V$7 zt>7Xr-8$ZI-RWqD!Bm3mVxUn^@LZ29ncAGOsNGNwz|EQt9G*Pav&s(|+F&YuX2tS* zd>3ydlVtaO;jaTvJ#CT#sfw9S&1xpHF!^9NWJ%{xTg*)uv25@U--uyK$u3R)I^_k!rP`NLlzQbFVKa=sff7W8qVntjnQ5BF2?sUO-Zm+9!E3x%cL9D!763x6&lT} z5nmWoqT&8vQM#g0wDa@_l{zJX^0-R#Wwifs)$WgIvqN!Gjm=X5HGF`zyWiAe6vq&( z$@(TOIElbA;jPz!9OnVRk5hoYeSS$y1v$`8LBlVfeuR-Wb`z*0kIPOJx7XDnYtJUL zv{c*YGfa6S)Vjs~CB{&8!)a8#|4+#3r~EhyKCI3?f-K&sfH!p>-8nCODzw|m_Up?{ zj!yGh{!S^!kk^LOD3~i5!pz!GUcd!EkQ|m5mRL#ybeSL``OHw9-#J794Z$ouTukrv zA*r`ny+WoDOQ?t~BQt-XT@e z?7UaPB2~=yqVIaeHSmw&$GY>$_H3bWdc+!>{`5RHbf+n~FWndrovK1#=+^Dc5sd#F ztkamJ#Lxh;ZZ{>kt)>xm=b_2r3-NnR@83-r$Ba$UI{mDGgMcqEjl# zFn}+>n+;fCNc z$RnMqkC^)t58rpby?bInA5+pOO=;XvK%jUHOIhF2eqFEnAlASQm|xg2_+cJ~3Q9KC zsTAKx8WX;m4G87y^J3Q|BvwRuapk1wcy|XR#6;;7L zf?H|jbo{}k5$-qhfz2$KHNub5)AT3Oj*^2@>$L!nK9u75O{M~$c-h6D$D>Np6HMMV8z8EXB1&I%t zp?!Hi{lxryZ^t4NhO<(9~L5E#!Vr68Y4UG6K}~VUd3YPfY>GUmP5GbBc&e-f<4kOxYrOhuJCk# zG(KKRKi*o}jBCvY`VW+i2-RS?T>Xsu%ORc9lrTpZH^6$`HI(B$UKtKnYebU*oYzh<&g`Fa zT;Ce03{JGi^-9AjtGa>y^3$i2C0YoLZV^J7azg78U^<04#Df}v!*sESs<_->Dn){< znQ))n#~kypl4{MQ_(%|Pu`}@M=IhP*$$f@XUVBqzZkC6ishVGk?RVDBIm%F?c(@@0 z%waL`b)2N8eAMhs-1&{E57_T8IPa4S2Dgs>SjO3x;YA#ji7gMU^Ka|aa*HWX-@te) zdp}856qG=^?;U)UDbrJZa!W#Q&FFz*{DOn(};-aR=%;HoD)6;-8s^BX7F ziM>1aWovwT>o)lNZ-mj5tZ57&viYjf_J05 zjQBj!J7)`5g7QjN65vkfK#oy5sH(5x_FuNU8U5W)C*L11vJJ?~Xf0(4*omBgh zS2SLa)(XZfj=X46D6r!9NE3xw(}OP0X=k$vN=U(p1NW9YLD~c+vs0OJ+oHftxyt#B*t>FBWJFQH@%m|Op{{{{@=!oxigt+w!OhCFz3=a%&Yx|y6l(u&J#SRd#z%tr@tpye9D6zPEoY`#b6CpQ`)Ir z{5AW%Eg3~cs%n&$E7t3EzuMY}`ArRN(+f7>QHI=U=I;KQ<1K0=&+E@sm2=JCo6vvi z0UL}-;uAda^7TA_bDHJV*IPFI&xJ};V6I;vJF)+(aZ=ApZ+T*>F>vBikIiX}owcz@ zaQ(zRZ)oP48%%!BN~z@5V8V%>Zu1jeu^c)05hW~?kM=DeK3{CDvJ0mSCNA_WIrlH* zTknL;S*iEa%JG+wY5Y5d#viEFh6yfuGW<^AOX<4A6+|32zK;~*^uxUERoHxJ>SDIw z0X1cyGSn6plWP31-p!NSvy;&FvX}S`tqw?t|Lh zgzGz~<1wGiL!D!$9(3hf3w)}~(NJLWOs(-26Cb(|in7?hoSGS~Q$W>6CD$r|ZV zf*Wd&dwRMWH=E&*NqLKKx*=Vl`rN#--rd(d$fK8a7&w+Q(U>cNuzLKO7?5Z+FMBd& zVn6ri!P)5s)o7|dW4*CBsXW)mICyG$U5MSrW=XWNG0{QcT3&Y znnw1iBL-407>^<>E_Uolsi3~tKtPT5iAXy$rAPIu+AHsi0tq99?d6SQ1JzNo(a@68~9BCA|p<-S9(|VJKC$lksf=A z`r0?<6Xw{-Pn=pl8(I+XxgoX=Y2v=_hVgO+DwFP3&qrkHFYUke zv&uKO?PQ_qcWn=+9L!^FvZ5S-^K2e0kqeNKsZw_4{a29}(0$NBy*iYgY2HX?S)73u zRf-798FcU0^;mDRUM%L}7e}FV*wbE{pjUv6~(*S1%@WB7g`gy9lx4B@cvG z$mInDT|mO19r**s3!5J)|CP`91Exn0fQCl!n6x8C>{k6Xi5D8-F)hy$Qyat;~fX}eLy)aPf}Jb@>~dJ7LyiGR8HW?349X0*qw`;-ouS*zV0!I zBkN0z-TZ#}%3}1ZKcot?5Yb(VWvMLI+4WvbU<`tQ=KgIln+`NP&Maih_9QC;ixc+g zQbtz-_LC@3@>UUa!*ZpI;@^HRy3{1T_SBhgdVPe)l5jCKc<$IK@fHUKLe+~XG+ZG0YF(gGr?sB z#&XLy?I&Tmy$6MTq+jPWv3C5mlhJujTWcN8jI*L;suE65EVkF81IEnqlNF842@>_e zNVhh?VMy~ArSbNb=Ieud5yak@$Vz~pj{Iuu+bB7o-?G_RPd<$(dtLdE z^lE9M%dPPIq%!s$a>_?18HR?KXpxANGaRXl?DpGpia$PLO(< z=hs8*yvx@neywY8TK4UVqx`_Nhz#}%mM}Mwn;>@cPw%e;;KX2kEXk^7=w@G$X{0w| zAwMfARh2>{%->Wu8OH^_?0>nkv(y%9zFm5jc_IW#{T8$p!7{@8zSTI?lJQPo9JIQjs2pXb3)&S{ z)QIioi9g$`M1C$=PuW}@y(1&G%4`8`h5VJ8OSHJ1?*M_6@n&Kb5IBAavyE+WY?Y4r zRWgoqn1o)p-!ld{LViBiZzv*pIF zLr-9##LTW_3)q+B*&3!sTpRbl)fA2oSD*r6?R7rT-rxu%_@f`Y?j(}V>wr>t$xR1T z+j}a`m#)kMjUIxfit90X#y{%6>j;Hy_g-UF-Ml&0&<~iWcA|jQezv>Te8N_!vCdo^ zZcyznFsFeVn#$QDG}qbD7DFuA>pCvjC?hGWPYJFRL zncHF)m>*9rK0(+|t7wK@D*2h!InbztA@Z#@#NRSij2}S{t)7k+opIK|^1_ z{hO8gbB(|CnGOBzauXSnaGyRKxE%ZRa8CFvW0cN;SEnwEQ7@ZY7Ummrw4eKa%njVj zcDHWXajvY;BO>uBl-m@ft{rA-unV?-9BfE1B5YIR0@M+Cn*)uiP-Y<9KbW4@)#ZN@ zs?D02vJ2%$ph6HD$7v6e29QMGqx0QJ_zjaS11nha?9a|5>^4(Qjl^w`C3nmZgNs!f z^+;b*oDv~W%-@-Ouig@r$vitGcFtsB%Is%ds9LM?_ndu8?6RQ?SN^0UFHK%zkv1-6%#3CaUve`Uuv&o;j97kaW(v-(Q>oGU}6Q_6EyQ5V{9*T@0VHNv&2r ztidCfWB|< z_L})C`cjIkp2E&4gF`-U$dpbXOIn$A-w3N}2+sqQn~q;XKbvG)WofF+D`_W6=DBwl zma}cW0a#`N?25=>Fd04WvPjCp4t+vVyLcdEoQD6bLLdGAAzK8x_U^v`_QFM}N-k)D zdA2{=%&Ks)_VXWQG1ts#-+@(vjc=>2tuM5m0npsds-_@^|DB2kiSCcw{Ol06ysKSk zo91^ex>zNJ-~87W=$Vi*1OLi%t2SgSC;m@+XByVjwf22Hoa#9hp-NFez*?$UQ4naD z6WXF+9iUWZ2tg8v5)g#|LK2`-0U1S#j3HL4%n1-sW<+KLA_Wo>hFIp1KnM^ZgyCI5 zdxqyZ&$*uWeLlSJhj(3m@Y-aDy%%fkeXsxhyZ@^@eCq8syMTL917_EN^|e@wUt&JgmI5t|Fx-;za`KTErLEJIgL=$gC|_4-VBAPZMZttJzc=C^oHMP>clhn$!k|; zfWBBeW6?g{$713H8;Qo7XZz>)n|`ZxrGZ68s)N4m)2c#w4p05gcO)QRX@Q4(VAb69 z2{|v-SIlM`tlAfrj3Mcc@Q*6g(f66n;WLr?bE^Z^t(9d_VvSz3)PyaAkkW#8d#>;jhS3b zODj5Q>Ho8IrvZB<_(*X3?a7qiw+itz|4%Tv>Uq~_qw6S4!eI7kv#9y~qk2@G@#yc9 ziD$#+XSZUl@Ze4JJ<(=VGO!XioW7}!fj#(lF;F7qCUUj)k&Gy3US7oNym{FC;4+L_ zom*ti$f;U*Wc(+oyGLZV4xNbz{wCqF{tYMj76%qTGK!oUb?BX4XOtFD9y4m*(brH1nwHICxL8`h8B|8O)I91X{Z?QCt`H0Ou2Ki*mn+(4?n|KY2%Rb5h> zLL_NBCwi1bVKc__Uaf9SY_b#yxRtYv4MT;}H#QqmHv#}>?_*0SNxR2nW)8R1v1L&)j}nTOE9<6NBRKx4 zy%c(prCPQ9?{|iDrG}q3pnoKgMCRg67P=vy!AX{?5yC}9!jvPQTa?(AY^+mTFC)w6KB+JEdbcdjHuuo|W zNk!`;wGSFK9$SX%A7yNQAy5z}jOtW`7BBFNt3O&BGohT50>)r^#QNJVT51s`H|y4# z{1c*EIw%hK&!Eb+YKLkkH$hgNuocVaa7{|~7acK)*^0ctu=j5DSq-tRzZ3CyK{=X% zYFBCqePP-!a&1L3syE_MA-3jW2|4e;Z?%z0T1_T~;(yMpf2m5*m7?&PE_*AuWyS4v zKd@IYe90%prHMe=-z)2<+3lDe_R3bEEV%tv`fI+}{I`|a&?tsMihSoLtDp$@4XDt3 zQi3N@BscGQpND$&n)@W8DN?tQri&I7ID%B7r_NW$0+Tws$J1KFE6luVbS;b>rcfOg zttaO=yna<&$c4nTzz2N$WfEOxQ*#*G<_g8&y;|yXT1%QEYByqk6J(3a z3pm-`YkV-^^rlqZo3+%9>Ys|k#?^}HahO&km;SzwUQRvTW2ol*`q)^gb+jMeclI;; zAM+h6+m6XTnh#8rwdhM#w+K@*!Ire-VU}-zF6uy(Jc$0TJ8tsSVZk@Xxf8V|M#Mmo zN()34ShPi2E)|(`(tJCW<923$`~>r?=yE)k-1Pt@iu+IU@;>J%rl?!M(KR;s)ns{) z|4pr#8#Scauo0NVP?#^n6NtQ>9g)XstFqGk8z92l z19O>ds|35Djbee`7iO%l%G>kD^}1SPdva?M1o?B8lp?BwfBfau-cz@N;QCl>;HGY& zD|RZKAjll$E;EwVL54Yb^eB#eIuF*SWNcQx_LILn#%hB~rLlv54g2(3bNd)~ZU~7f zq-w1OZf9coOVE@QW>uukJX6S1Q7K_7%p~$v;kR)>qd)tj({*NGW77d&MTH1`JJX?g zH_h=XH&k?DtY+5|*W`mre;Q`#)2lCvg$mw%AGRs|?ub-*9mLa-bfB)X>Lv1O8W}!Udwm1j=p(2h8NuKdJwJAS1*g`_ zXBAv**X}HZ)Tm8(E$QJbmY`1Zid*Srhe+w#jbSJA3d=r@O99ezPq_F`=B5;jRYg0z zab;iAWOvS&xrQxuBxxh+r#Ut4b?+-#cbg_KD%e`}tQP zr!yTm%Y*b|HITMQ45^!Mf&Na6`Hb!1(m>r^G z_^3Nn46LnowH8cV;iL7t_Pm3dLZvd?Sy)bfZc0Cs)p4VzH=x0Mig5ycFHJ8t)qkEg ztlDsyov3Jsx>JhDZ8+o7sM)(M>{x@(fCA)2DW5D4>?~HcXTkh)9D7piam+UedEpB|{uNfRo6Q#gS!qU#xbG&WDVNDBUp{BDv{>poawZS!Pnww^GAJ%qw)eVbVCPu0!HO#WZy~%F;Z#>I_rg) z$%GLn@-sOs^}=-&jNCFXF~1l#gc~LFm7y79I=CWJyPBFXCfCWe*59jIA9O@&w-U4d zd3$?t%C+Q@gn0VJ=d?V_poKzG7ljOclv*P2_bA4bgT>@!mo;=CHL_PNo;x9~9X}JI z$9BLr`5JvCMQeC^Jzn-GA|?&?Mcrnfmx2AHt>p1yCvYlrLS@xyT2|-lKP%~Pd$EHK zvc>Wcf;$!`(T^KtPwJ`h3bT^Q3R(C4gTH7~HLkpcRSVnAHOLkx+Ri9>(P~@J6?w)u z4VMWH=z&wyDPd9S;1&z5i2Xm_1KB;rYQA2CL>J2N2X$TH%n*VN}`-$7w{BGGRxva_68kTMD(@rw& zW1kCFQ)y-9j6U<*&vBk9Vy<4s!4k;PtL)hvr!A~E^2N!yI$MW2H`QWr&vUsr1xoS( zb@<@6JUq)1MES&MHo3lT=}G-SFyhTB;J5CY1>kGq@jM<;HB6-E!0=2;Lons}z;=_> zL5^1!bWSEtV!eyUUz(whZD}+Dt=VTd7HXkDN)4#|wuT3zc5+pi2Px>){Gggj*0U6f zs`#n12~OLMeKV=**IQIvF4@ZJ!V7&}7pi(5+!&WvZdn$KDPKM}-HXDRkvZag(!#2N zy0Jdaf*ahzq^zB1JNQNoKa_p-;=7V}mKP8w^oA#ck{anuTZx!Vu%zvcx<2w;ITC1hwrFg?Z&p4)u+PNv8+z1t^&dBpc&_xdN99On>2 zkmNiLcZyUm-*}(`mq#*_)wP6hIRlPv$Q?OTNoTBvq4}qxboP1WC2_m8*{52fn%P-Q zdD@?G^S;SGDF@eZt|lHQV0~(|i&lAU#_9OwYsNnpbqANwcmjUXcz;2H!j&9m2FIja zdxa&==`{LQ!5}xcXd*3r>Zv-q9X1H*d(a%ia~pisp;oW&k-)6aC1`kIf{4qix+dde zoFRG4=O$c_?XY@S`zXCL3EnWAc}Cl5YbbDP>7uCv#;+pGA={)O7~3@OwEgF*`biu3GQB&~-aZe4%VDcm)y|Tfcc4^`azE z39wp7t(V8>!zR&TH+M3v2c>wPiaH2^t3GrCm(@4TR2q9=Jrh3%Qi00c&){z4rO%Dv zxcJksQP%7e$HZ0tN^Kc_R{ah##B5j_7c{RL$LX-@8ypn8sj6UqlE%A+d=}<~qE)FI z3Aq-qIPacB@Wk}8d=Y#aSA!-dRZhA1*B`6JCkb_8*NV~Hx6H`C!!!tZXVm}p(Mz-l z9pS5Id*4M>Kj~sS1#bESzT!)&bgOLUx`L^yo8b7sloCc-YGMCO8`qzs_Yo+wNqx4* z5pkdZ))xN4>lv2;{JUV(>1JNM^y0G@{T+XLbvpYfWq&oOYjmM*{`K}gwHpE86M!P2 z`duCt_1}PGP19xY&U%Y}dLD93>u3GVg0@zK+@=hI0uu(I zL!j;l*ppbgqIZyR`ygC(;Ln_GUXx!!CVU5mSkw3HiIjxKip?1auQwc@H!nq4H~Fm; zUpVfmpIchzTcJ$nTwDA2HX#wGaIAT=b5hYR!LA!6-cz_#bd+Sr*0a@PLZ_1`9B)KN zj*s?t+vNI`R%cO4v8uQ}EACR_%p-zw#-QtkAd2_3NGFZF&s~ld(0PV4CLM_q$C00y zP8uFo_m4#c1EWt|xD(fQQxN|iS->{%xVxH|Wgca)+AMcZXV-QP!wI2P*?{uY= zoDTGR2l~222bKxhIm=2_86Eaqd6%}(?Z7rIIKIU2fmeh~rcJ%x`>vm}vPN@C5_#+x z?C{(;45*t!Mf;L4uzY7{CXRU|>n~FfeWDU|J-e4d=+9}jjF&vBU(=J6?{p^VC-8I% z*W>-mJeKosAx#T6`nWcFWbqg6RVaS^xEI6I+|r?4JGbkCLn8ACg;@^^S2gmmH&bBN z7fF{U-HGZ=;z55IX~|64=JA%-R11!^4lI_f)flf1WzH2}yF#!+W(SLMIy-&p6mmBz zxSG<7WLF?f_kkJp&InjjK!=2H`=z1!5rXRlfuR=*j273Fw#U4${`{p!N?+d;C0G%< ze)TzLsfVKW_P1mITcM}VlfQ?aEz`aDzDgSvk8FTfgNF(6%&op0$qTqvKMv#2n@E`3 zf`BOfAirk?>wntVD7&O{EKY}MXZE6jWul7H9d}BbIz@l2#V%5=g%AnOB?duLPvuFu zHQ+V~AmkX9wv>ZHj)#8Tqh`8&y{h7JozyT1N79**3*LW5UN47U3H~ zEjRW#74ulL{R2K*WY={@?m92@FetUd0kN14F8mZUdsA8y`OIimzlACG%2i|4W}c(X z{_YI%Uabi|7rfb}Tz=+72GpXWiOz%`WdFs&%&WKs9RyA3FVWG~Xl9UGd0f~2yZ{wD zJvi>X0;#(_H9fRWbxaON`4H}S`K9K4h<8ADpJBAcLZ3b|QmiPASSFYj}Ak)KF`++$WA{P)or5^`@fT>It!C_rO? z0F6Y=to!N+2+#zaIglb*1j)qWeTiz{mx=U)zN)pT^jcYrV+2F4=OicD<$6(q*Ha;= z^7c1;{lvbs;)6=e)H`3mGDdcnoSUmNyxg5h#$-;z_GZs?+Z8_rl9ewuS*w=jvt$ek zY`7WFLgKBGAkHMFy&<38I|ja)rLI*l%p1!u+Kr&Q=>WY<>m4iL*%Xgw@=W8a^_XKx zm<`y*>sYdbQSDEOh@8F+Rlv_fbznunvs4O*zQV<_Xgq#>c26oK;%UE%3LM$@UMN2R?0Hw+o~8w+Bu$PDqzB7br}OUmPkceki7;Qr&)BeqONqjEU?tFneZR z-GygtfWq7DQ!oIKH%(>`GaA&z-%{%N8QJQ#cl3;FjKdx{X&L(m@vgz;iH7kV3w8(M zd3_jlditmdE7;?O7sH5soT|P+OoW!5EC(nDpTP|n@g;5!P1TlkEjQaHDH7=n)xACQtZzARZzqWA!*o{rb+yH=}&7k8x&XRxX zkxmW^X)EB+E%vqQ4u@O(hhT+hg&dWHD(O?NXS=FVBxPWesm{8t(pi8oSaPz(1Z7L2 zxbpgI%zh{rUwoGRh`Tj3g)2_7sjFlcWy8NklPqvhM#lvWSgJ(NrTv1q_Yuu}@YU<( zr%{HoAj1vXLtvdS4sxqnlVCQ32<5=ucSoX+b0AD%$ur3TDgK|O7vsQ(oE>2z(e61C z$Jh6o?0;#iuzTh|p{utC_pHC)p#h;GKHFjzUI!9ol6G5jSJss`C9P_>z(gr$KOFui zS=XiF!_ogQ>w;eWKa_Q)M&eQfuF!sRA>sr|SlxOvM0g#ExtvdT%+yy4)kZE< zrtNV{I4fPMy1s_L`!_w;v^Z)_>-aL)xkhVhVmWJ%;n(ValCrFtGD2{ijoNQ9@s}BE zd7Mm20Waj&83)hhUVIbx&Kqb|T(4W$7iyJq(KF-Yd)5zrEKt^uN5SUWkW$+zqX{u; zhjJJ2?}}BSr|rT&e#as z++Q4vo9C#wOzF0%jitHd082*r%+ReMRx2oZGs`LQ@(Y1AbN&0Iikm(Q8~#bTlfT^D z9cxQMi9CeT&!L+YCvSbLP&2mH9L?zy%251HYCIBEUIWFBszy0Z(tXMDX7wu=$cSfj z&)h?XV3eNT&8Kz)GY$L6Qx;A#J(i` zz~>PmRKWcA)u*ki9Zi*?E@w>Wfjrp+F7Vb+B|wKWTJ0M6UH3ah0Q24P@I>dOAup0> z(ZKpG?NZwK#KiT6L~KINM;Sd%re5oc=(|i0R1&&%deCrq!zMsmB;e&R>r4>p4;ZPdtr8r=+IP~tF3roVYD*Mqy{_x1N%UKp4c;vvDGce=mVCDP#1OP_Q-69U`_Fk zb>O5*g0;$ILSN2dP`-o(>Xjfqlizn_F7by}yLg@;p3aM*4&ML3_f%HNKq(v zE}0#=)+*tv8WI=!V@i@}*n#f*N|(*kx{B(Pf4M@>r*jTf#2J3O3xB z{?siApt{9UmRX(0K4!_}j%TT^*lc${Rxq*%e7j330$A7NcC9~e>{R~}AX+ktub=^@ z$pmZKm@8JP?2l724s3b3)ZN0Av^gLr`(O{EMbF~Z4n@%}R9XX^?!Ay0R;cx>I2D-c zaW-=1EmKMeZ&N1-1L82!LiYuWAdpCSK!ytH4-RJ7wzg9s7QiQ26@mg(D;AX0F%{6m z2<5k*N;l?N%!n=md!3To=X(=DV)ggRwVPkW-CqlQPwEzt7K|Emf!(4P!(MT;@z5@v zTJ=Tmq8o^AO42P`sR4Q@einY`?VL|kq6%^vh-D56B)hBx=8rC&ea50+_gVft6L?BC zgQt|rKZ&dG!V=EE2orvDNN^{PpCM=8KMo2gSELr6Ko2dKO1Cx*bCY}jflKz6=ZfCn zqZ{!k+-MLsnz6rm<$_X_nS5PXI3-*=<$6cXU3N@{7O?t6U{JI_{i4!I?{lIbr)utE z8N68Pq$Auh0Z&}pJ9^ z!?_s&w_iIpG%P%5%2td;Yh7`0O_}d!j?J_BpBZZuuCG^GtYzDd2GXb(cfnMj9 zF{9@(u0M~F;j5PwJcIeElQZCb!4p8&M8$=XJouHzbBsA=xQQ4tU$AOrZ#Ejx(3RHc zciw@)V||<}Ca4tt!NWwYeXbf|_jT@gx&44b0A%~blU{3V#9bSv=s~ z3dU^0bqz#qua0?8#<6Mi0O2am3#ZXR5+tUk@vvjee)H6@XH)lzS7qBdoF&(*#$J{MZuwVDTue-H7;s8!aSWP_ z0cu|J_cd4CMx<#fB&A(<=^4P)p-Br}7e>+^Vb)spuD^&jSuH--U+JHylw0SBAKzFA zd7KPrkb;!HO!ysr(PJd%`_1w?%vQG-F5IEP;=C%=nOKGi4+O)P%2knX+%y?px!#y; z)G^{on;TOaw0^GH1(w~aaFA%xPU={Askn|AH4OI6nQux|5lY!ajUM%_z+H9oG&4Q& zh9niN|5W?%LAl6YuX7bv@%ja^Oo~w7-rrs}{Xf#N)Mfzq? zVhcJuVz_Akns|RoT@mpAsi3yy&y{MnR}BP@YQrBlUZGRl(11^!63-GEpR4E9S_e;l zo-_K~A)Erq`Rkw&f=PXS1q2gRy{=)Ef5Jyh#?JtCv)36B?bguFM!RN$!ktRvT#U8C zjFpUue-IJrL6=snG5t;JFwUN{r@Ce_`E;3YqFi@IW_ac${XA*VZfQ+@<>@KTh#^KId}QF zo3DQXu`TUjy}`?|$lCl>U2wX@{j^kJ%Ol%m^YiRWj9l4Qzd^)Q7dVdRM}~pId_BZs z=!n1E!c%J6u?H?W60I|->z6%_ayDBQ?&4*`P3Hb{Ie}6QC%hPB>j!E#rO2RQ(g8W+ z*6@DkJz&VKaWrCwFzX@@u$aBlw|lH=!PPFbQwPsTOiEuh?HOvA=Poy^J=rl`Dfw#> z`%kM#hBaa)+IKs^2ILFL%q{1ctOvcy=5m4c;pZKq$-r3JoNb&3VX`hIHY_d@)WYg^ z%Bq>k`_);zsr0ioIluePwSa+@mf6pz%H^(~Cs{P3?2ww>nbTzG>m`VDz|CxQIYAxH z1a}Abs${kDbP!rh#Hb>R3m0Rf#vio~YzmEonb+ota9k;<3LD)bXU?~o{Zn^K7hm!hB-g;GMfmLXSBbRNCn_aCGy%G=Cd2}{@5PvMf+7&lhw_rRb6ZF>T^a2jT8~0xL9e~Uxu?RS_H=OKLArUylFQhncP?U zh?(7ri~^!y+F6U$yY?Wqpq3nitUaPs#qPelK7Vu7zDS|Go&B-~#IePbL)>22;6EU# zWtiN0K$vneiOZqTHxAL4($-9x#m>j8qkQ7^afDn$2Yqhlk`62KZoOGF%!~y`h>EkF13oN#+T0Wp0QQ|?x>(%K+dh_lqCB=K7ku;tEuZ7sv22Nq!2P~ zA&!5Kto%gPMb$;)r@fkgRV-m1L>KMvj9GKOVs$treBS}!z7X7C-{D>P6bWYSEg2J$ zagDY5i!r$e7R3TMDE%T9hdmv;3+GQ5dm80;Yvp?q^n4M7`kZcX5>Ujajo@rxO?Ok5>3ylzzkK?QfuTu2ax&za zrSh5PVR`mZV83N65MUCL57eM74=828m5AvmOi(LR?ndm7>}z*obiJ0qtMtA)&{8N? zGL(92b*D3R6qEU6GI0`jDn^5450$BJr!7 zAM^T6;T!K9kYz=8Kw4{KL2%%LgB9IWv={w89D!V;?k&PtrxjM0j88C>N879d4KR~v zNniDe1z}+4#R#;ANZuV{85+TAHiF5Zua?e!Wj&Z_lY5wQ?B;;3 zvHxjyZI7o$l#}|QquHv}4|{B^=vVBv110lmP9p6N7dsWt>OTb4X_%lEQ81oXwnTEy z9O-9}8bzb&oKYerKGnHos0_>_;BC(^^6Jo9Zr+Tqq1>eT@KK?bf$|i7G3ip;?84MR z3Gx~62l9DoER}oN0~iXIW;IKfs)cz^cz*F_s}^>n*~vHv0}<*X%&&4G_|0;op>DPlY*+ zRfc&{>l-x@>Q57$N_vMX8;x~%9n8SQ2Z(K=WQ(H?71TmG8kFqKY4j^h@d`7QVT*`b+=3mjX2f3kf6`1KS?PEcBr5(1B}vBE9a>DTCMXpepEz0(^U{bM z=kL(LTjGa6bL_H$Tbw|3%K>bIY&|}ykyiB;Le<_o(1MY38pNVOlRV@0pQ1)=&MuT| z&@BfTCC51O8QE41#vn+09&o>VZQXQUQqvO%3!ci4x&X+{!Zz^YS!j}IcI`Iij|qM5 ztEnMimYvm7eF7d??y7s=9nGc0ph*`U^;!U7xu~|Q%8jUj<9Zu^c8t8U+9|Qb23v!H zFM0_QaZL1UXq@+c-1OQ!+LAtwM zVJ27>0mu;jNaA2BX)oV-OP3NhaOF*FGjWZ9z+_v}f@i#?7u#pn*ld#i%Jy2xTQfwS z8U4cxe&k+}%qxW1Du*93v?bagoDKWfhho-CN$7iN$@T|vgQV5z5AS=otMaf(+g^;V z2%nvu(w!ZX^zH3dCj-~!??JW?w8afqVVZkF3~6t87)i8NxwV7c-Z{%yw=Vn;I6$i3 zNM!?K*(n$D`y&yI@#}vC7!jD)f0Ww%SGzg=TM4vrpZgYkL}}Y%_gcVQzW1;9A^dPH zAUpaV2>owtDe`~qgX_=_vaeK~?!O;6uMpuoW?z5f?YQoF%S+M&-(9dePyW{Z-v0st CEBN~W literal 0 HcmV?d00001