-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[net] Add libcurl based support for files on HTTP remotes #19842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
2655124
[CMake] add 'curl' build option
jblomer b14c282
[net] add libCurlHttp skeleton
jblomer 8949e94
[net] add functional version of RCurlConnection
jblomer 369e8b3
[net] add debug output to RCurlConnection
jblomer 861ea04
[net] add functional version of RRawFileCurl
jblomer f2e03a5
[net] add TCurlFile skeleton
jblomer 4a5b055
[net] add basic TCurlFile implementation
jblomer 3a83d04
add Curl.ReplaceDavix option to rootrc
jblomer 4f915de
style fix in RRawFile::Create() plugin selection
jblomer afd3fa1
add RRawFileCurl plugin
jblomer d389111
add TCurlFile plugin
jblomer ee3b300
fix HTTP availability check in unit tests
jblomer 1b75b5d
[ci] enable curl build option
jblomer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,5 +2,6 @@ builtin_gtest=ON | |
| builtin_nlohmannjson=ON | ||
| builtin_tbb=ON | ||
| builtin_vdt=ON | ||
| curl=OFF | ||
| pythia8=ON | ||
| tmva-sofie=ON | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,7 @@ clingtest=OFF | |
| cocoa=OFF | ||
| coverage=OFF | ||
| cuda=OFF | ||
| curl=ON | ||
| daos=OFF | ||
| dataframe=ON | ||
| davix=ON | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| void P015_RRawFileCurl() | ||
| { | ||
| TString configfeatures = gROOT->GetConfigFeatures(); | ||
|
|
||
| if (configfeatures.Contains("curl") && | ||
| (!configfeatures.Contains("davix") || gEnv->GetValue("Curl.ReplaceDavix", 0))) { | ||
|
|
||
| gPluginMgr->AddHandler("ROOT::Internal::RRawFile", "^http[s]?:", "ROOT::Internal::RRawFileCurl", "RCurlHttp", | ||
| "RRawFileCurl(std::string_view, ROOT::Internal::RRawFile::ROptions)"); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| void P140_TCurlFile() | ||
| { | ||
| TString configfeatures = gROOT->GetConfigFeatures(); | ||
|
|
||
| if (configfeatures.Contains("curl") && | ||
| (!configfeatures.Contains("davix") || gEnv->GetValue("Curl.ReplaceDavix", 0))) { | ||
|
|
||
| gPluginMgr->AddHandler("TFile", "^http[s]?:", "TCurlFile", "RCurlHttp", "TCurlFile(const char *, Option_t *)"); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # For the licensing terms see $ROOTSYS/LICENSE. | ||
| # For the list of contributors see $ROOTSYS/README/CREDITS. | ||
|
|
||
| ############################################################################ | ||
| # CMakeLists.txt file for building ROOT net/curl package | ||
| # @author Jakob Blomer, CERN | ||
| ############################################################################ | ||
|
|
||
| ROOT_STANDARD_LIBRARY_PACKAGE(RCurlHttp | ||
| HEADERS | ||
| ROOT/RCurlConnection.hxx | ||
| ROOT/RRawFileCurl.hxx | ||
| TCurlFile.h | ||
| SOURCES | ||
| src/RCurlConnection.cxx | ||
| src/RRawFileCurl.cxx | ||
| src/TCurlFile.cxx | ||
| LIBRARIES | ||
| CURL::libcurl | ||
| DEPENDENCIES | ||
| RIO | ||
| ) | ||
|
|
||
| if(NOT MSVC) | ||
| target_compile_options(RCurlHttp PRIVATE -Wno-deprecated-declarations) | ||
| endif() | ||
|
|
||
| ROOT_ADD_TEST_SUBDIRECTORY(test) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| #ifdef __CLING__ | ||
|
|
||
| #pragma link C++ class ROOT::Internal::RRawFileCurl+; | ||
| #pragma link C++ class TCurlFile+; | ||
|
|
||
| #endif | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| // @(#)root/net:$Id$ | ||
| // Author: Jakob Blomer | ||
|
|
||
| /************************************************************************* | ||
| * Copyright (C) 1995-2025, Rene Brun and Fons Rademakers. * | ||
| * All rights reserved. * | ||
| * * | ||
| * For the licensing terms see $ROOTSYS/LICENSE. * | ||
| * For the list of contributors see $ROOTSYS/README/CREDITS. * | ||
| *************************************************************************/ | ||
|
|
||
| #ifndef ROOT_RCurlConnection | ||
| #define ROOT_RCurlConnection | ||
|
|
||
| #include <ROOT/RError.hxx> | ||
|
|
||
| #include <cstdint> | ||
| #include <memory> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| namespace ROOT { | ||
| namespace Internal { | ||
|
|
||
| /// Encapsulates a curl easy handle and provides an interface to send HTTP HEAD and (multi-)range queries. | ||
| class RCurlConnection { | ||
| public: | ||
| /// Return value for both HEAD and GET requests. In case of errors, provides the reason for the failure as code | ||
| /// and as message. | ||
| struct RStatus { | ||
| enum EStatusCode { | ||
| kSuccess = 0, | ||
| kTooManyRanges, ///< should not get to the user; number of request ranges is automatically reduced as needed | ||
| kNotFound, | ||
| kIOError, | ||
| kUnknown | ||
| }; | ||
|
|
||
| EStatusCode fStatusCode = kUnknown; | ||
| std::string fStatusMsg; | ||
|
|
||
| RStatus() = default; | ||
| explicit RStatus(EStatusCode code) : fStatusCode(code) {} | ||
|
|
||
| explicit operator bool() const { return fStatusCode == kSuccess; } | ||
| }; | ||
|
|
||
| private: | ||
| void *fHandle = nullptr; ///< the CURL easy handle corresponding to this connection | ||
| /// If set to zero, automatically adjust: try with all given ranges and as long as the number of ranges is too large, | ||
| /// half it. If set to zero and automatic reduction of the number of requests is necessary, the number of requests | ||
| /// that works will be saved for further requests with this object. | ||
| std::size_t fMaxNRangesPerReqest = 0; | ||
| std::string fEscapedUrl; ///< The URL provided in the constructor escaped according to standard rules | ||
| std::unique_ptr<char[]> fErrorBuffer; ///< For use by libcurl | ||
|
|
||
| void SetupErrorBuffer(); | ||
| void SetOptions(); | ||
| RResult<void> SetUrl(const std::string &url); | ||
| void Perform(RStatus &status); | ||
|
|
||
| public: | ||
| /// Returned by SendHeadReq() if the HTTP response contains no content-length header | ||
| static constexpr std::uint64_t kUnknownSize = static_cast<std::uint64_t>(-1); | ||
|
|
||
| /// Caller-provided byte-range of the remote resource together with a pointer to a buffer. | ||
| struct RUserRange { | ||
| unsigned char *fDestination = nullptr; | ||
| std::uint64_t fOffset = 0; | ||
| std::size_t fLength = 0; | ||
| /// Usually equal to fLength for a successful call unless range goes out of the size of the remote resource | ||
| std::size_t fNBytesRecv = 0; | ||
|
|
||
| bool operator<(const RUserRange &other) const { return fOffset < other.fOffset; } | ||
| }; | ||
|
|
||
| explicit RCurlConnection(const std::string &url); | ||
| ~RCurlConnection(); | ||
| RCurlConnection(const RCurlConnection &other) = delete; | ||
| RCurlConnection &operator=(const RCurlConnection &other) = delete; | ||
| RCurlConnection(RCurlConnection &&other); | ||
| RCurlConnection &operator=(RCurlConnection &&other); | ||
|
|
||
| /// Checks if the resource exists and if it does, return the value of the content-length header as size | ||
| RStatus SendHeadReq(std::uint64_t &remoteSize); | ||
| /// Reads the given ranges from the remote resource. The ranges can be in any order and also overlapping. They | ||
| /// will be transformed in optimized HTTP ranges for a multi-range request. Ranges past the resource size are | ||
| /// valid (but won't receive any data). No limit on the number of ranges; if fMaxNRangesPerReqest is zero, | ||
| /// a valid batching of requests into multiple multi-range requests takes place automatically. | ||
| /// The fNBytesRecv member of the ranges is only well-defined on success. | ||
| RStatus SendRangesReq(std::size_t N, RUserRange *ranges); | ||
|
|
||
| const std::string &GetEscapedUrl() const { return fEscapedUrl; } | ||
|
|
||
| void SetMaxNRangesPerRequest(std::size_t val) { fMaxNRangesPerReqest = val; } | ||
| std::size_t GetMaxNRangesPerRequest() const { return fMaxNRangesPerReqest; } | ||
| }; | ||
|
|
||
| } // namespace Internal | ||
| } // namespace ROOT | ||
|
|
||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // @(#)root/net:$Id$ | ||
| // Author: Jakob Blomer | ||
|
|
||
| /************************************************************************* | ||
| * Copyright (C) 1995-2025, Rene Brun and Fons Rademakers. * | ||
| * All rights reserved. * | ||
| * * | ||
| * For the licensing terms see $ROOTSYS/LICENSE. * | ||
| * For the list of contributors see $ROOTSYS/README/CREDITS. * | ||
| *************************************************************************/ | ||
|
|
||
| #ifndef ROOT_RRawFileCurl | ||
| #define ROOT_RRawFileCurl | ||
|
|
||
| #include <ROOT/RRawFile.hxx> | ||
|
|
||
| #include <memory> | ||
|
|
||
| namespace ROOT { | ||
| namespace Internal { | ||
|
|
||
| class RCurlConnection; | ||
|
|
||
| /// \class RRawFileCurl | ||
| /// \ingroup net | ||
| /// | ||
| /// The RRawFileCurl class reads HTTP(S) resources using the curl library. The passed URL of the file | ||
| /// needs to start with http:// or https://. The URL does not need to be escaped; URL encoding is handled internally. | ||
| class RRawFileCurl : public RRawFile { | ||
| private: | ||
| std::unique_ptr<RCurlConnection> fConnection; | ||
|
|
||
| protected: | ||
| void OpenImpl() final; | ||
| size_t ReadAtImpl(void *buffer, size_t nbytes, std::uint64_t offset) final; | ||
| void ReadVImpl(RIOVec *ioVec, unsigned int nReq) final; | ||
| std::uint64_t GetSizeImpl() final; | ||
|
|
||
| public: | ||
| static constexpr int kDefaultBlockSize = 128 * 1024; // relatively large 128k blocks for better network utilization | ||
|
|
||
| RRawFileCurl(std::string_view url, RRawFile::ROptions options); | ||
| ~RRawFileCurl(); | ||
| std::unique_ptr<RRawFile> Clone() const final; | ||
|
|
||
| RCurlConnection &GetConnection(); | ||
| }; | ||
|
|
||
| } // namespace Internal | ||
| } // namespace ROOT | ||
|
|
||
| #endif |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.