From efe620bc8814a244362c12ace8d0377965667074 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 1 Sep 2026 12:41:33 +0200 Subject: [PATCH 1/2] Keep the libcurl header out of CcdbApi.h Moves the libcurl dependency out of the public `CcdbApi.h` header and keeps it in the implementation where it belongs. This makes the header self-contained and allows ROOT to interpret it without requiring the curl headers. --- CCDB/include/CCDB/CcdbApi.h | 28 ++++++++++-------- CCDB/src/CcdbApi.cxx | 58 +++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index 0c95090e98fec..ad5b50af90de7 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include "CCDB/CcdbObjectInfo.h" @@ -37,7 +36,9 @@ class TJAlienCredentials; #endif -#include "CCDB/CCDBDownloader.h" +// libcurl and the downloader are implementation details of CcdbApi.cxx; +// only opaque handles appear below, so neither header is needed here. +struct curl_slist; class TFile; #include @@ -48,6 +49,7 @@ namespace ccdb { class CCDBQuery; +class CCDBDownloader; /** * Interface to the CCDB. @@ -57,6 +59,9 @@ class CCDBQuery; * @todo handle errors and exceptions * @todo extend code coverage */ +/// stands in for libcurl's `typedef void CURL` without including +using CurlHandle = void; + class CcdbApi //: public DatabaseInterface { public: @@ -342,7 +347,7 @@ class CcdbApi //: public DatabaseInterface * @param curl curl handler * @return */ - static void curlSetSSLOptions(CURL* curl); + static void curlSetSSLOptions(CurlHandle* curl); TObject* retrieve(std::string const& path, std::map const& metadata, long timestamp) const; @@ -442,7 +447,7 @@ class CcdbApi //: public DatabaseInterface * @param handle CURL handle associated with the request. * @param requestCounter Pointer to the variable storing the number of requests to be done. */ - void asynchPerform(CURL* handle, size_t* requestCounter) const; + void asynchPerform(CurlHandle* handle, size_t* requestCounter) const; // internal helper function to update a CCDB file with meta information static void updateMetaInformationInLocalFile(std::string const& filename, std::map const* headers, CCDBQuery const* querysummary = nullptr); @@ -478,7 +483,7 @@ class CcdbApi //: public DatabaseInterface * @param endValidityTimestamp End of validity. If omitted or negative, current timestamp + 1 day is used. * @return The full url to store an object (url / startValidity / endValidity / [metadata &]* ) */ - std::string getFullUrlForStorage(CURL* curl, const std::string& path, const std::string& objtype, + std::string getFullUrlForStorage(CurlHandle* curl, const std::string& path, const std::string& objtype, const std::map& metadata, long startValidityTimestamp = -1, long endValidityTimestamp = -1, int hostIndex = 0) const; @@ -489,7 +494,7 @@ class CcdbApi //: public DatabaseInterface * @param timestamp When the object we retrieve must be valid. If omitted or negative, the current timestamp is used. * @return The full url to store an object (url / startValidity / endValidity / [metadata &]* ) */ - std::string getFullUrlForRetrieval(CURL* curl, const std::string& path, const std::map& metadata, + std::string getFullUrlForRetrieval(CurlHandle* curl, const std::string& path, const std::map& metadata, long timestamp = -1, int hostIndex = 0) const; public: @@ -564,14 +569,13 @@ class CcdbApi //: public DatabaseInterface /// Queries the CCDB server and navigates through possible redirects until binary content is found; Retrieves content as instance /// given by tinfo if that is possible. Returns nullptr if something fails... - void* navigateURLsAndRetrieveContent(CURL*, std::string const& url, std::type_info const& tinfo, std::map* headers) const; + void* navigateURLsAndRetrieveContent(CurlHandle*, std::string const& url, std::type_info const& tinfo, std::map* headers) const; // helper that interprets a content chunk as TMemFile and extracts the object therefrom static void* interpretAsTMemFileAndExtract(char* contentptr, size_t contentsize, std::type_info const& tinfo); /** - * Initialization of CURL - */ + * Initialization of CurlHandle*/ void curlInit(); // convert type_info to TClass, throw on failure @@ -579,10 +583,10 @@ class CcdbApi //: public DatabaseInterface typedef size_t (*CurlWriteCallback)(void*, size_t, size_t, void*); - void initCurlOptionsForRetrieve(CURL* curlHandle, void* pointer, CurlWriteCallback writeCallback, bool followRedirect = true) const; + void initCurlOptionsForRetrieve(CurlHandle* curlHandle, void* pointer, CurlWriteCallback writeCallback, bool followRedirect = true) const; /// initialize HTTPS header information for the CURL handle. Needs to be given an existing curl_slist* pointer to work with (may be nullptr), which needs to be free by the caller. - void initCurlHTTPHeaderOptionsForRetrieve(CURL* curlHandle, curl_slist*& option_list, long timestamp, std::map* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, std::string_view url) const; + void initCurlHTTPHeaderOptionsForRetrieve(CurlHandle* curlHandle, curl_slist*& option_list, long timestamp, std::map* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, std::string_view url) const; bool receiveToFile(FILE* fileHandle, std::string const& path, std::map const& metadata, long timestamp, std::map* headers = nullptr, std::string const& etag = "", @@ -628,7 +632,7 @@ class CcdbApi //: public DatabaseInterface // tmp helper and single point of entry for a CURL perform call // helps to switch between easy handle perform and multi handles in a single place - CURLcode CURL_perform(CURL* handle) const; + int CURL_perform(CurlHandle* handle) const; // returns a CURLcode mutable CCDBDownloader* mDownloader = nullptr; //! the multi-handle (async) CURL downloader bool mIsCCDBDownloaderPreferred = false; diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index a22b078fed972..bb9af397d527b 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -15,6 +15,8 @@ /// #include "CCDB/CcdbApi.h" +#include "CCDB/CCDBDownloader.h" +#include #include "CCDB/CCDBQuery.h" #include "CommonUtils/StringUtils.h" @@ -480,7 +482,7 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin } // Curl preparation - CURL* curl = nullptr; + CurlHandle* curl = nullptr; curl = curl_easy_init(); // checking that all metadata keys do not contain invalid characters @@ -520,7 +522,7 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); /* Perform the request, res will get the return code */ - res = CURL_perform(curl); + res = static_cast(CURL_perform(curl)); /* Check for errors */ if (res != CURLE_OK) { if (res == CURLE_OPERATION_TIMEDOUT) { @@ -558,7 +560,7 @@ int CcdbApi::storeAsTFile(const TObject* rootObject, std::string const& path, st return storeAsBinaryFile(img->data(), img->size(), info.getFileName(), info.getObjectType(), path, metadata, startValidityTimestamp, endValidityTimestamp, maxSize); } -std::string CcdbApi::getFullUrlForStorage(CURL* curl, const std::string& path, const std::string& objtype, +std::string CcdbApi::getFullUrlForStorage(CurlHandle* curl, const std::string& path, const std::string& objtype, const std::map& metadata, long startValidityTimestamp, long endValidityTimestamp, int hostIndex) const { @@ -589,7 +591,7 @@ std::string CcdbApi::getFullUrlForStorage(CURL* curl, const std::string& path, c } // todo make a single method of the one above and below -std::string CcdbApi::getFullUrlForRetrieval(CURL* curl, const std::string& path, const std::map& metadata, long timestamp, int hostIndex) const +std::string CcdbApi::getFullUrlForRetrieval(CurlHandle* curl, const std::string& path, const std::map& metadata, long timestamp, int hostIndex) const { if (mInSnapshotMode) { return getSnapshotFile(mSnapshotTopPath, path); @@ -674,7 +676,7 @@ static size_t WriteToFileCallback(void* ptr, size_t size, size_t nmemb, FILE* st * @param parm * @return */ -static CURLcode ssl_ctx_callback(CURL*, void*, void* parm) +static CURLcode ssl_ctx_callback(CurlHandle*, void*, void* parm) { std::string msg((const char*)parm); int start = 0, end = msg.find('\n'); @@ -691,7 +693,7 @@ static CURLcode ssl_ctx_callback(CURL*, void*, void* parm) return CURLE_OK; } -void CcdbApi::curlSetSSLOptions(CURL* curl_handle) +void CcdbApi::curlSetSSLOptions(CurlHandle* curl_handle) { CredentialsKind cmk = mJAlienCredentials->getPreferedCredentials(); @@ -719,7 +721,7 @@ void CcdbApi::curlSetSSLOptions(CURL* curl_handle) using CurlWriteCallback = size_t (*)(void*, size_t, size_t, void*); -void CcdbApi::initCurlOptionsForRetrieve(CURL* curlHandle, void* chunk, CurlWriteCallback writeCallback, bool followRedirect) const +void CcdbApi::initCurlOptionsForRetrieve(CurlHandle* curlHandle, void* chunk, CurlWriteCallback writeCallback, bool followRedirect) const { curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, writeCallback); curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, chunk); @@ -774,7 +776,7 @@ size_t header_map_callback(char* buffer, size_t size, size_t nitems, void* userd } } // namespace -void CcdbApi::initCurlHTTPHeaderOptionsForRetrieve(CURL* curlHandle, curl_slist*& option_list, long timestamp, std::map* headers, std::string const& etag, +void CcdbApi::initCurlHTTPHeaderOptionsForRetrieve(CurlHandle* curlHandle, curl_slist*& option_list, long timestamp, std::map* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, std::string_view url) const { // struct curl_slist* list = nullptr; @@ -823,7 +825,7 @@ bool CcdbApi::receiveObject(void* dataHolder, std::string const& path, std::map< long timestamp, std::map* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, bool followRedirect, CurlWriteCallback writeCallback) const { - CURL* curlHandle; + CurlHandle* curlHandle; curlHandle = curl_easy_init(); curl_easy_setopt(curlHandle, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); @@ -843,7 +845,7 @@ bool CcdbApi::receiveObject(void* dataHolder, std::string const& path, std::map< curl_slist* option_list = nullptr; initCurlHTTPHeaderOptionsForRetrieve(curlHandle, option_list, timestamp, headers, etag, createdNotAfter, createdNotBefore, fullUrl); - curlResultCode = CURL_perform(curlHandle); + curlResultCode = static_cast(CURL_perform(curlHandle)); if (curlResultCode != CURLE_OK) { LOGP(alarm, "curl_easy_perform() failed: {}", curl_easy_strerror(curlResultCode)); @@ -1104,7 +1106,7 @@ void* CcdbApi::interpretAsTMemFileAndExtract(char* contentptr, size_t contentsiz } // navigate sequence of URLs until TFile content is found; object is extracted and returned -void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string const& url, std::type_info const& tinfo, std::map* headers) const +void* CcdbApi::navigateURLsAndRetrieveContent(CurlHandle* curl_handle, std::string const& url, std::type_info const& tinfo, std::map* headers) const { // a global internal data structure that can be filled with HTTP header information // static --> to avoid frequent alloc/dealloc as optimization @@ -1131,7 +1133,7 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con curlSetSSLOptions(curl_handle); - auto res = CURL_perform(curl_handle); + auto res = static_cast(CURL_perform(curl_handle)); long response_code = -1; void* content = nullptr; bool errorflag = false; @@ -1250,7 +1252,7 @@ void* CcdbApi::retrieveFromTFile(std::type_info const& tinfo, std::string const& // normal mode follows - CURL* curl_handle = curl_easy_init(); + CurlHandle* curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); std::string fullUrl = getFullUrlForRetrieval(curl_handle, path, metadata, timestamp); // todo check if function still works correctly in case mInSnapshotMode // if we are in snapshot mode we can simply open the file; extract the object and return @@ -1299,7 +1301,7 @@ size_t CurlWrite_CallbackFunc_StdString2(void* contents, size_t size, size_t nme std::string CcdbApi::list(std::string const& path, bool latestOnly, std::string const& returnFormat, long createdNotAfter, long createdNotBefore) const { - CURL* curl; + CurlHandle* curl; CURLcode res = CURL_LAST; std::string result; @@ -1332,7 +1334,7 @@ std::string CcdbApi::list(std::string const& path, bool latestOnly, std::string headers = appendGateToken(headers, fullUrl); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - res = CURL_perform(curl); + res = static_cast(CURL_perform(curl)); if (res != CURLE_OK) { LOGP(alarm, "CURL_perform() failed: {}", curl_easy_strerror(res)); } @@ -1353,7 +1355,7 @@ std::string CcdbApi::getTimestampString(long timestamp) const void CcdbApi::deleteObject(std::string const& path, long timestamp) const { - CURL* curl; + CurlHandle* curl; CURLcode res; long timestampLocal = timestamp == -1 ? getCurrentTimestamp() : timestamp; @@ -1377,7 +1379,7 @@ void CcdbApi::deleteObject(std::string const& path, long timestamp) const curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); // Perform the request, res will get the return code - res = CURL_perform(curl); + res = static_cast(CURL_perform(curl)); if (res != CURLE_OK) { LOGP(alarm, "CURL_perform() failed: {}", curl_easy_strerror(res)); } @@ -1391,7 +1393,7 @@ void CcdbApi::deleteObject(std::string const& path, long timestamp) const void CcdbApi::truncate(std::string const& path) const { - CURL* curl; + CurlHandle* curl; CURLcode res; for (size_t i = 0; i < hostsPool.size(); i++) { // Declared inside the loop: a stringstream hoisted out of it accumulates, @@ -1416,7 +1418,7 @@ void CcdbApi::truncate(std::string const& path) const curlSetSSLOptions(curl); // Perform the request, res will get the return code - res = CURL_perform(curl); + res = static_cast(CURL_perform(curl)); if (res != CURLE_OK) { LOGP(alarm, "CURL_perform() failed: {}", curl_easy_strerror(res)); } @@ -1433,7 +1435,7 @@ size_t write_data(void*, size_t size, size_t nmemb, void*) bool CcdbApi::isHostReachable() const { - CURL* curl; + CurlHandle* curl; CURLcode res = CURL_LAST; bool result = false; @@ -1455,7 +1457,7 @@ bool CcdbApi::isHostReachable() const curl_easy_setopt(curl, CURLOPT_URL, mUrl.data()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curlSetSSLOptions(curl); - res = CURL_perform(curl); + res = static_cast(CURL_perform(curl)); result = (res == CURLE_OK); } @@ -1561,7 +1563,7 @@ std::map CcdbApi::retrieveHeaders(std::string const& p { // lambda that actually does the call to the CCDB server auto do_remote_header_call = [this, &path, &metadata, timestamp]() -> std::map { - CURL* curl = curl_easy_init(); + CurlHandle* curl = curl_easy_init(); CURLcode res = CURL_LAST; std::string fullUrl = getFullUrlForRetrieval(curl, path, metadata, timestamp); std::map headers; @@ -1587,7 +1589,7 @@ std::map CcdbApi::retrieveHeaders(std::string const& p CURLcode getCodeRes = CURL_LAST; for (size_t hostIndex = 0; hostIndex < hostsPool.size() && (httpCode >= 400 || res > 0 || getCodeRes > 0); hostIndex++) { curl_easy_setopt(curl, CURLOPT_URL, fullUrl.c_str()); - res = CURL_perform(curl); + res = static_cast(CURL_perform(curl)); if (res != CURLE_OK && res != CURLE_UNSUPPORTED_PROTOCOL) { // We take out the unsupported protocol error because we are only querying // header info which is returned in any case. Unsupported protocol error @@ -1747,7 +1749,7 @@ TClass* CcdbApi::tinfo2TClass(std::type_info const& tinfo) int CcdbApi::updateMetadata(std::string const& path, std::map const& metadata, long timestamp, std::string const& id, long newEOV) { int ret = -1; - CURL* curl = curl_easy_init(); + CurlHandle* curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); if (curl != nullptr) { CURLcode res; @@ -1788,7 +1790,7 @@ int CcdbApi::updateMetadata(std::string const& path, std::map(CURL_perform(curl)); if (res != CURLE_OK) { LOGP(alarm, "CURL_perform() failed: {}, code: {}", curl_easy_strerror(res), int(res)); ret = int(res); @@ -1857,7 +1859,7 @@ void CcdbApi::scheduleDownload(RequestContext& requestContext, size_t* requestCo return realsize; }; - CURL* curl_handle = curl_easy_init(); + CurlHandle* curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); std::string fullUrl = getFullUrlForRetrieval(curl_handle, requestContext.path, requestContext.metadata, requestContext.timestamp); @@ -2269,12 +2271,12 @@ void CcdbApi::logReading(const std::string& path, long ts, const std::mapasynchSchedule(handle, requestCounter); } -CURLcode CcdbApi::CURL_perform(CURL* handle) const +int CcdbApi::CURL_perform(CurlHandle* handle) const { if (mIsCCDBDownloaderPreferred) { return mDownloader->perform(handle); From 10df9ffc49e45d2068d49973ed05a80ae718d09e Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Tue, 1 Sep 2026 10:44:27 +0000 Subject: [PATCH 2/2] Please consider the following formatting changes --- CCDB/include/CCDB/CcdbApi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index ad5b50af90de7..c0414afc9bebf 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -632,7 +632,7 @@ class CcdbApi //: public DatabaseInterface // tmp helper and single point of entry for a CURL perform call // helps to switch between easy handle perform and multi handles in a single place - int CURL_perform(CurlHandle* handle) const; // returns a CURLcode + int CURL_perform(CurlHandle* handle) const; // returns a CURLcode mutable CCDBDownloader* mDownloader = nullptr; //! the multi-handle (async) CURL downloader bool mIsCCDBDownloaderPreferred = false;