13 #include <string_view>
17 #include <curl/curl.h>
23 namespace fs = std::filesystem;
26 const char path_separator =
':';
27 const char*
const pathResolverEnvVar =
"PATHRESOLVER_DEVAREARESPONSE";
30 size_t write_data(
void*
ptr,
size_t size,
size_t nmemb,
void* userdata) {
31 std::ostream*
stream =
static_cast<std::ostream*
>(userdata);
32 size_t total_size =
size * nmemb;
33 stream->write(
static_cast<char*
>(
ptr), total_size);
36 bool download_file(
const std::string&
url,
const std::string& output_path,
43 static std::once_flag curl_setup;
44 std::call_once(curl_setup, curl_global_init, CURL_GLOBAL_DEFAULT);
46 using owner_t = std::unique_ptr<CURL, decltype(&curl_easy_cleanup)>;
47 owner_t curl_owner(curl_easy_init(), curl_easy_cleanup);
49 auto* curl = curl_owner.get();
52 asgmsg.
msg(MSG::WARNING) <<
"unable to setup curl" <<
endmsg;
56 std::ofstream
file(output_path, std::ios::binary);
57 if (!
file.is_open()) {
58 asgmsg.
msg(MSG::WARNING) <<
"unable to open " << output_path <<
endmsg;
61 auto setCurlOption =[curl](
auto option,
const auto &
value)->
bool{
62 CURLcode ret = curl_easy_setopt(curl, option,
value);
63 return (ret == CURLE_OK);
65 bool setupOk = setCurlOption(CURLOPT_TIMEOUT, 60
L);
66 setupOk &= setCurlOption(CURLOPT_URL,
url.c_str());
67 setupOk &= setCurlOption(CURLOPT_WRITEFUNCTION, write_data);
68 setupOk &= setCurlOption(CURLOPT_WRITEDATA, &
file);
70 setupOk &= setCurlOption(CURLOPT_FOLLOWLOCATION, 1
L);
72 asgmsg.
msg(MSG::WARNING) <<
"curl setup failed in PathResolver." <<
endmsg;
75 CURLcode
res = curl_easy_perform(curl);
76 if (
res != CURLE_OK) {
77 asgmsg.
msg(MSG::WARNING) <<
"error downloading file: "
78 << curl_easy_strerror(
res)
88 const std::string& logical_file_name) {
92 if (logical_file_name.starts_with(
"dev/")) {
94 const std::string dev_area_response =
env ?
env :
"DEFAULT";
97 if (dev_area_response ==
"SILENT") {
100 else if (dev_area_response ==
"THROW") {
101 throw std::runtime_error(
102 "Loading dev area file " + logical_file_name +
" is not allowed! "
103 "To override this error set the environment variable " +
104 pathResolverEnvVar +
" to SILENT, DEFAULT, INFO, WARNING or ERROR");
106 else if (dev_area_response ==
"DEFAULT") {
108 level = MSG::WARNING;
114 else if (dev_area_response ==
"WARNING")
level = MSG::WARNING;
115 else if (dev_area_response ==
"ERROR")
level = MSG::ERROR;
117 throw std::runtime_error(
std::format(
"{} set to '{}', not sure what to do. "
118 "Options are DEFAULT, THROW, INFO, WARNING, ERROR or SILENT",
119 pathResolverEnvVar, dev_area_response));
123 asgmsg.
msg(
level) <<
"Locating dev file " << logical_file_name <<
". Do not let this propagate to a release!" <<
endmsg;
130 #ifdef XAOD_STANDALONE
135 #ifndef XAOD_ANALYSIS
149 fs::file_type file_type, std::string&
result ) {
152 TString tmpString(logical_file_name);
153 gSystem->ExpandPathName(tmpString);
156 fs::path locationToDownloadTo =
".";
159 const std::string searchPath =
std::format(
"./{}{}", path_separator, search_list);
163 std::string_view
path(
r.begin(),
r.end());
164 const bool is_http =
path.starts_with(
"http//");
165 if( (is_http ||
path.starts_with(
"https//")) &&
170 const std::string fileToDownload =
std::format(
"{}://{}/{}", is_http ?
"http" :
"https",
173 const fs::path targetPath = locationToDownloadTo /
file;
175 targetDir.remove_filename();
176 msg(
MSG::DEBUG) <<
"Attempting http download of " << fileToDownload <<
" to " << targetDir <<
endmsg;
178 if (!is_directory(targetDir)) {
180 if(!fs::create_directories(targetDir)) {
181 msg(MSG::ERROR) <<
"Unable to create directories to write file to " << targetDir <<
endmsg;
186 if (!download_file(fileToDownload, targetPath,
asgMsg())) {
187 msg(MSG::WARNING) <<
"Unable to download file " << fileToDownload <<
endmsg;
194 }
else if (locationToDownloadTo==
".") {
197 std::ofstream ofs(dummyFile);
199 locationToDownloadTo =
path;
211 }
catch (
const fs::filesystem_error&) {
222 const std::string& search_path) {
224 #ifndef XAOD_ANALYSIS
225 if (logical_file_name.starts_with(
'/')) {
226 msg(MSG::ERROR) <<
"Use of an absolute file name: " << logical_file_name <<
endmsg;
232 msg(MSG::ERROR) << search_path <<
" environment variable not defined!" <<
endmsg;
241 const std::string& search_list)
251 const std::string& search_path)
255 msg(MSG::ERROR) << search_path <<
" environment variable not defined!" <<
endmsg;
264 const std::string& search_list)
275 checkForDev(
asgMsg(), logical_file_name);
277 if (logical_file_name.starts_with(
"root://")) {
279 std::unique_ptr<TFile> fTmp{TFile::Open(logical_file_name.c_str())};
280 if (!fTmp || fTmp->IsZombie()) {
281 msg(MSG::WARNING) <<
"Could not open " << logical_file_name <<
endmsg;
284 return logical_file_name;
289 msg(MSG::WARNING) <<
"Could not locate " << logical_file_name <<
endmsg;
297 checkForDev(
asgMsg(), logical_file_name);
301 msg(MSG::WARNING) <<
"Could not locate " << logical_file_name <<
endmsg;