|
42 | 42 | #include "ROOT/RNTupleDS.hxx" |
43 | 43 | #endif |
44 | 44 |
|
| 45 | +#ifdef R__UNIX |
| 46 | +// Functions needed to perform EOS XRootD redirection in ChangeSpec |
| 47 | +#include <optional> |
| 48 | +#include "TEnv.h" |
| 49 | +#include "TSystem.h" |
| 50 | +#ifndef R__FBSD |
| 51 | +#include <sys/xattr.h> |
| 52 | +#else |
| 53 | +#include <sys/extattr.h> |
| 54 | +#endif |
| 55 | +#ifdef R__MACOSX |
| 56 | +/* On macOS getxattr takes two extra arguments that should be set to 0 */ |
| 57 | +#define getxattr(path, name, value, size) getxattr(path, name, value, size, 0u, 0) |
| 58 | +#endif |
| 59 | +#ifdef R__FBSD |
| 60 | +#define getxattr(path, name, value, size) extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, value, size) |
| 61 | +#endif |
| 62 | +#endif |
| 63 | + |
45 | 64 | #include <algorithm> |
46 | 65 | #include <atomic> |
47 | 66 | #include <cassert> |
@@ -403,6 +422,38 @@ RLoopManager::RLoopManager(ROOT::RDF::Experimental::RDatasetSpec &&spec) |
403 | 422 | ChangeSpec(std::move(spec)); |
404 | 423 | } |
405 | 424 |
|
| 425 | +#ifdef R__UNIX |
| 426 | +namespace { |
| 427 | +std::optional<std::string> GetRedirectedSampleId(std::string_view path, std::string_view datasetName) |
| 428 | +{ |
| 429 | + // Mimick the redirection done in TFile::Open to see if the path points to a FUSE-mounted EOS path. |
| 430 | + // If so, we create a redirected sample ID with the full xroot URL. |
| 431 | + TString expandedUrl(path.data()); |
| 432 | + gSystem->ExpandPathName(expandedUrl); |
| 433 | + if (gEnv->GetValue("TFile.CrossProtocolRedirects", 1) == 1) { |
| 434 | + TUrl fileurl(expandedUrl, /* default is file */ kTRUE); |
| 435 | + if (strcmp(fileurl.GetProtocol(), "file") == 0) { |
| 436 | + ssize_t len = getxattr(fileurl.GetFile(), "eos.url.xroot", nullptr, 0); |
| 437 | + if (len > 0) { |
| 438 | + std::string xurl(len, 0); |
| 439 | + std::string fileNameFromUrl{fileurl.GetFile()}; |
| 440 | + if (getxattr(fileNameFromUrl.c_str(), "eos.url.xroot", &xurl[0], len) == len) { |
| 441 | + // Sometimes the `getxattr` call may return an invalid URL due |
| 442 | + // to the POSIX attribute not being yet completely filled by EOS. |
| 443 | + if (auto baseName = fileNameFromUrl.substr(fileNameFromUrl.find_last_of("/") + 1); |
| 444 | + std::equal(baseName.crbegin(), baseName.crend(), xurl.crbegin())) { |
| 445 | + return xurl + '/' + datasetName.data(); |
| 446 | + } |
| 447 | + } |
| 448 | + } |
| 449 | + } |
| 450 | + } |
| 451 | + |
| 452 | + return std::nullopt; |
| 453 | +} |
| 454 | +} // namespace |
| 455 | +#endif |
| 456 | + |
406 | 457 | /** |
407 | 458 | * @brief Changes the internal TTree held by the RLoopManager. |
408 | 459 | * |
@@ -441,6 +492,11 @@ void RLoopManager::ChangeSpec(ROOT::RDF::Experimental::RDatasetSpec &&spec) |
441 | 492 | // is exposed to users via RSampleInfo and DefinePerSample). |
442 | 493 | const auto sampleId = files[i] + '/' + trees[i]; |
443 | 494 | fSampleMap.insert({sampleId, &sample}); |
| 495 | +#ifdef R__UNIX |
| 496 | + // Also add redirected EOS xroot URL when available |
| 497 | + if (auto redirectedSampleId = GetRedirectedSampleId(files[i], trees[i])) |
| 498 | + fSampleMap.insert({redirectedSampleId.value(), &sample}); |
| 499 | +#endif |
444 | 500 | } |
445 | 501 | } |
446 | 502 | SetTree(std::move(chain)); |
|
0 commit comments