diff --git a/.gitignore b/.gitignore index d458cd5c10..68086eead4 100644 --- a/.gitignore +++ b/.gitignore @@ -89,6 +89,7 @@ java/target java/test-libs java/*.log java/include/org_rocksdb_*.h +juicefs-hadoop-1.3.1.jar .idea/ *.iml diff --git a/build_tools/pack_server.sh b/build_tools/pack_server.sh index 53ee67bf30..85d62a7db9 100755 --- a/build_tools/pack_server.sh +++ b/build_tools/pack_server.sh @@ -168,6 +168,9 @@ if [ -n "$HADOOP_HOME" ]; then fi # Pack the jars. mkdir -p ${pack}/hadoop + + wget -N https://github.com/juicedata/juicefs/releases/download/v1.3.1/juicefs-hadoop-1.3.1.jar + copy_file ./juicefs-hadoop-1.3.1.jar ${pack}/hadoop for f in ${HADOOP_HOME}/share/hadoop/common/lib/*.jar; do copy_file $f ${pack}/hadoop done diff --git a/src/block_service/block_service_manager.cpp b/src/block_service/block_service_manager.cpp index 9ca1ed9561..b31417ce55 100644 --- a/src/block_service/block_service_manager.cpp +++ b/src/block_service/block_service_manager.cpp @@ -37,12 +37,19 @@ namespace dsn { namespace dist { namespace block_service { +const char *BLOCK_SERVICE_JUICEFS = "juicefs_service"; + block_service_registry::block_service_registry() { CHECK(utils::factory_store::register_factory( "hdfs_service", block_filesystem::create, PROVIDER_TYPE_MAIN), "register hdfs_service failed"); + // juice_service use hdfs_service as default provider + CHECK(utils::factory_store::register_factory( + BLOCK_SERVICE_JUICEFS, block_filesystem::create, PROVIDER_TYPE_MAIN), + "register juice_service failed"); + CHECK(utils::factory_store::register_factory( "local_service", block_filesystem::create, PROVIDER_TYPE_MAIN), "register local_service failed"); @@ -70,11 +77,17 @@ block_filesystem *block_service_manager::get_or_create_block_filesystem(const st return iter->second.get(); } - const char *provider_type = dsn_config_get_value_string( - (std::string("block_service.") + provider).c_str(), "type", "", "block service type"); + block_filesystem *fs = nullptr; + const char *provider_type = nullptr; + bool isJuicefs = is_juicefs_provider(provider); - block_filesystem *fs = - utils::factory_store::create(provider_type, PROVIDER_TYPE_MAIN); + if (isJuicefs) { + provider_type = BLOCK_SERVICE_JUICEFS; + } else { + provider_type = dsn_config_get_value_string( + (std::string("block_service.") + provider).c_str(), "type", "", "block service type"); + } + fs = utils::factory_store::create(provider_type, PROVIDER_TYPE_MAIN); if (fs == nullptr) { LOG_ERROR("acquire block filesystem failed, provider = {}, provider_type = {}", provider, @@ -82,15 +95,25 @@ block_filesystem *block_service_manager::get_or_create_block_filesystem(const st return nullptr; } - const char *arguments = dsn_config_get_value_string( - (std::string("block_service.") + provider).c_str(), "args", "", "args for block_service"); - std::vector args; - utils::split_args(arguments, args); + std::string args_for_log; + if (isJuicefs) { + // juicefs provider example: jfs://pegasus@ak-bigdata + args = {provider, "/"}; + args_for_log = provider + " /"; + } else { + const char *arguments = + dsn_config_get_value_string((std::string("block_service.") + provider).c_str(), + "args", + "", + "args for block_service"); + utils::split_args(arguments, args); + args_for_log = arguments; + } dsn::error_code err = fs->initialize(args); const auto provider_desc = fmt::format( - "provider = {}, provider_type = {}, args = {}", provider, provider_type, arguments); + "provider = {}, provider_type = {}, args = {}", provider, provider_type, args_for_log); if (dsn::ERR_OK == err) { LOG_INFO("create block filesystem ok for {}", provider_desc); _fs_map.emplace(provider, std::unique_ptr(fs)); diff --git a/src/block_service/block_service_manager.h b/src/block_service/block_service_manager.h index d945f259e3..45ed96cecf 100644 --- a/src/block_service/block_service_manager.h +++ b/src/block_service/block_service_manager.h @@ -17,11 +17,12 @@ #pragma once -#include +#include +#include +#include #include #include #include - #include "utils/error_code.h" #include "utils/singleton.h" #include "utils/zlocks.h" @@ -76,6 +77,23 @@ class block_service_manager /*out*/ uint64_t &download_file_size); private: + static bool is_juicefs_provider(const std::string &provider) + { + // provider example: jfs://pegasus@ak-bigdata + const std::string prefix = "jfs://"; + if (!absl::StartsWith(provider, prefix)) { + return false; + } + std::string remaining = provider.substr(prefix.size()); + size_t at_pos = remaining.find('@'); + if (at_pos == std::string::npos || at_pos == 0) { + return false; + } + // check has ak-bigdata + std::string host = remaining.substr(at_pos + 1); + return !host.empty(); + } + block_service_registry &_registry_holder; mutable zrwlock_nr _fs_lock; diff --git a/src/block_service/test/run.sh b/src/block_service/test/run.sh index b72d7e9c02..719185dc92 100755 --- a/src/block_service/test/run.sh +++ b/src/block_service/test/run.sh @@ -23,6 +23,26 @@ if [ -z "${REPORT_DIR}" ]; then REPORT_DIR="." fi +# By default, unit tests use local_service. +# To connect to HDFS/JuiceFS or other storage systems in unit tests, configure the corresponding paths. +package_dir="example: pegasus-server-2.4.8-without-slog-cb99c3e-glibc2.17-release absolute path" +echo $package_dir + +# Set the ld library path +ld_library_path=$package_dir/DSN_ROOT/lib:$package_dir/bin:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=$ld_library_path + +export CLASSPATH=$package_dir/hadoop/ +for f in $package_dir/hadoop/*.jar; do +export CLASSPATH=$CLASSPATH:$f +done +JAVA_JVM_LIBRARY_DIR=$(dirname $(find "${JAVA_HOME}/" -name libjvm.so | head -1)) +export LD_LIBRARY_PATH=${JAVA_JVM_LIBRARY_DIR}:$LD_LIBRARY_PATH + +echo CLASSPATH=$CLASSPATH +echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH +echo JAVA_JVM_LIBRARY_DIR=$JAVA_JVM_LIBRARY_DIR + ./clear.sh output_xml="${REPORT_DIR}/dsn_block_service_test.xml" GTEST_OUTPUT="xml:${output_xml}" ./dsn_block_service_test