/root/doris/be/src/util/path_util.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "util/path_util.h" |
19 | | |
20 | | // Use the POSIX version of dirname(3). See `man 3 dirname` |
21 | | #include <libgen.h> |
22 | | |
23 | | #include <cstdlib> |
24 | | #include <filesystem> |
25 | | |
26 | | #include "cloud/config.h" |
27 | | #include "common/config.h" |
28 | | #include "gutil/strings/split.h" |
29 | | #include "gutil/strings/strip.h" |
30 | | #include "runtime/plugin/cloud_plugin_downloader.h" |
31 | | |
32 | | using std::string; |
33 | | using std::vector; |
34 | | using strings::SkipEmpty; |
35 | | using strings::Split; |
36 | | |
37 | | namespace doris { |
38 | | namespace path_util { |
39 | | |
40 | 1.20k | std::string join_path_segments(const string& a, const string& b) { |
41 | 1.20k | if (a.empty()) { Branch (41:9): [True: 1, False: 1.20k]
|
42 | 1 | return b; |
43 | 1.20k | } else if (b.empty()) { Branch (43:16): [True: 1, False: 1.20k]
|
44 | 1 | return a; |
45 | 1.20k | } else { |
46 | 1.20k | return StripSuffixString(a, "/") + "/" + StripPrefixString(b, "/"); |
47 | 1.20k | } |
48 | 1.20k | } |
49 | | |
50 | | // strdup use malloc to obtain memory for the new string, it should be freed with free. |
51 | | // but std::unique_ptr use delete to free memory by default, so it should specify free memory using free |
52 | | |
53 | 21 | std::string dir_name(const string& path) { |
54 | 21 | std::vector<char> path_copy(path.c_str(), path.c_str() + path.size() + 1); |
55 | 21 | return dirname(&path_copy[0]); |
56 | 21 | } |
57 | | |
58 | 54 | std::string base_name(const string& path) { |
59 | 54 | std::vector<char> path_copy(path.c_str(), path.c_str() + path.size() + 1); |
60 | 54 | return basename(&path_copy[0]); |
61 | 54 | } |
62 | | |
63 | 42 | std::string file_extension(const string& path) { |
64 | 42 | string file_name = base_name(path); |
65 | 42 | if (file_name == "." || file_name == "..") { Branch (65:9): [True: 2, False: 40]
Branch (65:29): [True: 1, False: 39]
|
66 | 3 | return ""; |
67 | 3 | } |
68 | | |
69 | 39 | string::size_type pos = file_name.rfind("."); |
70 | 39 | return pos == string::npos ? "" : file_name.substr(pos); Branch (70:12): [True: 25, False: 14]
|
71 | 42 | } |
72 | | |
73 | | std::string get_real_plugin_url(const std::string& url, const std::string& plugin_dir_config_value, |
74 | 5 | const std::string& plugin_dir_name, const std::string& doris_home) { |
75 | 5 | if (url.find(":/") == std::string::npos) { Branch (75:9): [True: 3, False: 2]
|
76 | 3 | return check_and_return_default_plugin_url(url, plugin_dir_config_value, plugin_dir_name, |
77 | 3 | doris_home); |
78 | 3 | } |
79 | 2 | return url; |
80 | 5 | } |
81 | | |
82 | | std::string check_and_return_default_plugin_url(const std::string& url, |
83 | | const std::string& plugin_dir_config_value, |
84 | | const std::string& plugin_dir_name, |
85 | 7 | const std::string& doris_home) { |
86 | 7 | std::string home_dir = doris_home; |
87 | 7 | if (home_dir.empty()) { Branch (87:9): [True: 0, False: 7]
|
88 | 0 | const char* env_home = std::getenv("DORIS_HOME"); |
89 | 0 | if (env_home) { Branch (89:13): [True: 0, False: 0]
|
90 | 0 | home_dir = std::string(env_home); |
91 | 0 | } else { |
92 | 0 | return "file://" + plugin_dir_config_value + "/" + url; |
93 | 0 | } |
94 | 0 | } |
95 | | |
96 | 7 | std::string default_url = home_dir + "/plugins/" + plugin_dir_name; |
97 | 7 | std::string default_old_url = home_dir + "/" + plugin_dir_name; |
98 | | |
99 | 7 | if (plugin_dir_config_value == default_url) { Branch (99:9): [True: 5, False: 2]
|
100 | | // If true, which means user does not set `jdbc_drivers_dir` and use the default one. |
101 | | // Because in 2.1.8, we change the default value of `jdbc_drivers_dir` |
102 | | // from `DORIS_HOME/jdbc_drivers` to `DORIS_HOME/plugins/jdbc_drivers`, |
103 | | // so we need to check the old default dir for compatibility. |
104 | 5 | std::string target_path = default_url + "/" + url; |
105 | 5 | if (std::filesystem::exists(target_path)) { Branch (105:13): [True: 2, False: 3]
|
106 | | // File exists in new default directory |
107 | 2 | return "file://" + target_path; |
108 | 3 | } else if (config::is_cloud_mode()) { Branch (108:20): [True: 0, False: 3]
|
109 | | // Cloud mode: try to download from cloud to new default directory |
110 | 0 | CloudPluginDownloader::PluginType plugin_type; |
111 | 0 | if (plugin_dir_name == "jdbc_drivers") { Branch (111:17): [True: 0, False: 0]
|
112 | 0 | plugin_type = CloudPluginDownloader::PluginType::JDBC_DRIVERS; |
113 | 0 | } else if (plugin_dir_name == "java_udf") { Branch (113:24): [True: 0, False: 0]
|
114 | 0 | plugin_type = CloudPluginDownloader::PluginType::JAVA_UDF; |
115 | 0 | } else { |
116 | | // Unknown plugin type, fallback to old directory |
117 | 0 | return "file://" + default_old_url + "/" + url; |
118 | 0 | } |
119 | | |
120 | 0 | std::string downloaded_path; |
121 | 0 | Status status = CloudPluginDownloader::download_from_cloud( |
122 | 0 | plugin_type, url, target_path, &downloaded_path); |
123 | 0 | if (status.ok() && !downloaded_path.empty()) { Branch (123:17): [True: 0, False: 0]
Branch (123:32): [True: 0, False: 0]
|
124 | 0 | return "file://" + downloaded_path; |
125 | 0 | } |
126 | | // Download failed, log warning but continue to fallback |
127 | 0 | LOG(WARNING) << "Failed to download plugin from cloud: " << status.to_string() |
128 | 0 | << ", fallback to old directory"; |
129 | 0 | } |
130 | | |
131 | | // Fallback to old default directory for compatibility |
132 | 3 | return "file://" + default_old_url + "/" + url; |
133 | 5 | } else { |
134 | | // User specified custom directory - use directly |
135 | 2 | return "file://" + plugin_dir_config_value + "/" + url; |
136 | 2 | } |
137 | 7 | } |
138 | | |
139 | | } // namespace path_util |
140 | | } // namespace doris |