Skip to content

Commit efe620b

Browse files
committed
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.
1 parent 522a524 commit efe620b

2 files changed

Lines changed: 46 additions & 40 deletions

File tree

CCDB/include/CCDB/CcdbApi.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include <string_view>
2222
#include <memory>
2323
#include <map>
24-
#include <curl/curl.h>
2524
#include <TObject.h>
2625
#include <TMessage.h>
2726
#include "CCDB/CcdbObjectInfo.h"
@@ -37,7 +36,9 @@
3736
class TJAlienCredentials;
3837
#endif
3938

40-
#include "CCDB/CCDBDownloader.h"
39+
// libcurl and the downloader are implementation details of CcdbApi.cxx;
40+
// only opaque handles appear below, so neither header is needed here.
41+
struct curl_slist;
4142

4243
class TFile;
4344
#include <TGrid.h>
@@ -48,6 +49,7 @@ namespace ccdb
4849
{
4950

5051
class CCDBQuery;
52+
class CCDBDownloader;
5153

5254
/**
5355
* Interface to the CCDB.
@@ -57,6 +59,9 @@ class CCDBQuery;
5759
* @todo handle errors and exceptions
5860
* @todo extend code coverage
5961
*/
62+
/// stands in for libcurl's `typedef void CURL` without including <curl/curl.h>
63+
using CurlHandle = void;
64+
6065
class CcdbApi //: public DatabaseInterface
6166
{
6267
public:
@@ -342,7 +347,7 @@ class CcdbApi //: public DatabaseInterface
342347
* @param curl curl handler
343348
* @return
344349
*/
345-
static void curlSetSSLOptions(CURL* curl);
350+
static void curlSetSSLOptions(CurlHandle* curl);
346351

347352
TObject* retrieve(std::string const& path, std::map<std::string, std::string> const& metadata, long timestamp) const;
348353

@@ -442,7 +447,7 @@ class CcdbApi //: public DatabaseInterface
442447
* @param handle CURL handle associated with the request.
443448
* @param requestCounter Pointer to the variable storing the number of requests to be done.
444449
*/
445-
void asynchPerform(CURL* handle, size_t* requestCounter) const;
450+
void asynchPerform(CurlHandle* handle, size_t* requestCounter) const;
446451

447452
// internal helper function to update a CCDB file with meta information
448453
static void updateMetaInformationInLocalFile(std::string const& filename, std::map<std::string, std::string> const* headers, CCDBQuery const* querysummary = nullptr);
@@ -478,7 +483,7 @@ class CcdbApi //: public DatabaseInterface
478483
* @param endValidityTimestamp End of validity. If omitted or negative, current timestamp + 1 day is used.
479484
* @return The full url to store an object (url / startValidity / endValidity / [metadata &]* )
480485
*/
481-
std::string getFullUrlForStorage(CURL* curl, const std::string& path, const std::string& objtype,
486+
std::string getFullUrlForStorage(CurlHandle* curl, const std::string& path, const std::string& objtype,
482487
const std::map<std::string, std::string>& metadata,
483488
long startValidityTimestamp = -1, long endValidityTimestamp = -1, int hostIndex = 0) const;
484489

@@ -489,7 +494,7 @@ class CcdbApi //: public DatabaseInterface
489494
* @param timestamp When the object we retrieve must be valid. If omitted or negative, the current timestamp is used.
490495
* @return The full url to store an object (url / startValidity / endValidity / [metadata &]* )
491496
*/
492-
std::string getFullUrlForRetrieval(CURL* curl, const std::string& path, const std::map<std::string, std::string>& metadata,
497+
std::string getFullUrlForRetrieval(CurlHandle* curl, const std::string& path, const std::map<std::string, std::string>& metadata,
493498
long timestamp = -1, int hostIndex = 0) const;
494499

495500
public:
@@ -564,25 +569,24 @@ class CcdbApi //: public DatabaseInterface
564569

565570
/// Queries the CCDB server and navigates through possible redirects until binary content is found; Retrieves content as instance
566571
/// given by tinfo if that is possible. Returns nullptr if something fails...
567-
void* navigateURLsAndRetrieveContent(CURL*, std::string const& url, std::type_info const& tinfo, std::map<std::string, std::string>* headers) const;
572+
void* navigateURLsAndRetrieveContent(CurlHandle*, std::string const& url, std::type_info const& tinfo, std::map<std::string, std::string>* headers) const;
568573

569574
// helper that interprets a content chunk as TMemFile and extracts the object therefrom
570575
static void* interpretAsTMemFileAndExtract(char* contentptr, size_t contentsize, std::type_info const& tinfo);
571576

572577
/**
573-
* Initialization of CURL
574-
*/
578+
* Initialization of CurlHandle*/
575579
void curlInit();
576580

577581
// convert type_info to TClass, throw on failure
578582
static TClass* tinfo2TClass(std::type_info const& tinfo);
579583

580584
typedef size_t (*CurlWriteCallback)(void*, size_t, size_t, void*);
581585

582-
void initCurlOptionsForRetrieve(CURL* curlHandle, void* pointer, CurlWriteCallback writeCallback, bool followRedirect = true) const;
586+
void initCurlOptionsForRetrieve(CurlHandle* curlHandle, void* pointer, CurlWriteCallback writeCallback, bool followRedirect = true) const;
583587

584588
/// 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.
585-
void initCurlHTTPHeaderOptionsForRetrieve(CURL* curlHandle, curl_slist*& option_list, long timestamp, std::map<std::string, std::string>* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, std::string_view url) const;
589+
void initCurlHTTPHeaderOptionsForRetrieve(CurlHandle* curlHandle, curl_slist*& option_list, long timestamp, std::map<std::string, std::string>* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, std::string_view url) const;
586590

587591
bool receiveToFile(FILE* fileHandle, std::string const& path, std::map<std::string, std::string> const& metadata,
588592
long timestamp, std::map<std::string, std::string>* headers = nullptr, std::string const& etag = "",
@@ -628,7 +632,7 @@ class CcdbApi //: public DatabaseInterface
628632

629633
// tmp helper and single point of entry for a CURL perform call
630634
// helps to switch between easy handle perform and multi handles in a single place
631-
CURLcode CURL_perform(CURL* handle) const;
635+
int CURL_perform(CurlHandle* handle) const; // returns a CURLcode
632636

633637
mutable CCDBDownloader* mDownloader = nullptr; //! the multi-handle (async) CURL downloader
634638
bool mIsCCDBDownloaderPreferred = false;

CCDB/src/CcdbApi.cxx

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
///
1616

1717
#include "CCDB/CcdbApi.h"
18+
#include "CCDB/CCDBDownloader.h"
19+
#include <curl/curl.h>
1820
#include "CCDB/CCDBQuery.h"
1921

2022
#include "CommonUtils/StringUtils.h"
@@ -480,7 +482,7 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin
480482
}
481483

482484
// Curl preparation
483-
CURL* curl = nullptr;
485+
CurlHandle* curl = nullptr;
484486
curl = curl_easy_init();
485487

486488
// 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
520522
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
521523

522524
/* Perform the request, res will get the return code */
523-
res = CURL_perform(curl);
525+
res = static_cast<CURLcode>(CURL_perform(curl));
524526
/* Check for errors */
525527
if (res != CURLE_OK) {
526528
if (res == CURLE_OPERATION_TIMEDOUT) {
@@ -558,7 +560,7 @@ int CcdbApi::storeAsTFile(const TObject* rootObject, std::string const& path, st
558560
return storeAsBinaryFile(img->data(), img->size(), info.getFileName(), info.getObjectType(), path, metadata, startValidityTimestamp, endValidityTimestamp, maxSize);
559561
}
560562

561-
std::string CcdbApi::getFullUrlForStorage(CURL* curl, const std::string& path, const std::string& objtype,
563+
std::string CcdbApi::getFullUrlForStorage(CurlHandle* curl, const std::string& path, const std::string& objtype,
562564
const std::map<std::string, std::string>& metadata,
563565
long startValidityTimestamp, long endValidityTimestamp, int hostIndex) const
564566
{
@@ -589,7 +591,7 @@ std::string CcdbApi::getFullUrlForStorage(CURL* curl, const std::string& path, c
589591
}
590592

591593
// todo make a single method of the one above and below
592-
std::string CcdbApi::getFullUrlForRetrieval(CURL* curl, const std::string& path, const std::map<std::string, std::string>& metadata, long timestamp, int hostIndex) const
594+
std::string CcdbApi::getFullUrlForRetrieval(CurlHandle* curl, const std::string& path, const std::map<std::string, std::string>& metadata, long timestamp, int hostIndex) const
593595
{
594596
if (mInSnapshotMode) {
595597
return getSnapshotFile(mSnapshotTopPath, path);
@@ -674,7 +676,7 @@ static size_t WriteToFileCallback(void* ptr, size_t size, size_t nmemb, FILE* st
674676
* @param parm
675677
* @return
676678
*/
677-
static CURLcode ssl_ctx_callback(CURL*, void*, void* parm)
679+
static CURLcode ssl_ctx_callback(CurlHandle*, void*, void* parm)
678680
{
679681
std::string msg((const char*)parm);
680682
int start = 0, end = msg.find('\n');
@@ -691,7 +693,7 @@ static CURLcode ssl_ctx_callback(CURL*, void*, void* parm)
691693
return CURLE_OK;
692694
}
693695

694-
void CcdbApi::curlSetSSLOptions(CURL* curl_handle)
696+
void CcdbApi::curlSetSSLOptions(CurlHandle* curl_handle)
695697
{
696698
CredentialsKind cmk = mJAlienCredentials->getPreferedCredentials();
697699

@@ -719,7 +721,7 @@ void CcdbApi::curlSetSSLOptions(CURL* curl_handle)
719721

720722
using CurlWriteCallback = size_t (*)(void*, size_t, size_t, void*);
721723

722-
void CcdbApi::initCurlOptionsForRetrieve(CURL* curlHandle, void* chunk, CurlWriteCallback writeCallback, bool followRedirect) const
724+
void CcdbApi::initCurlOptionsForRetrieve(CurlHandle* curlHandle, void* chunk, CurlWriteCallback writeCallback, bool followRedirect) const
723725
{
724726
curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
725727
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
774776
}
775777
} // namespace
776778

777-
void CcdbApi::initCurlHTTPHeaderOptionsForRetrieve(CURL* curlHandle, curl_slist*& option_list, long timestamp, std::map<std::string, std::string>* headers, std::string const& etag,
779+
void CcdbApi::initCurlHTTPHeaderOptionsForRetrieve(CurlHandle* curlHandle, curl_slist*& option_list, long timestamp, std::map<std::string, std::string>* headers, std::string const& etag,
778780
const std::string& createdNotAfter, const std::string& createdNotBefore, std::string_view url) const
779781
{
780782
// struct curl_slist* list = nullptr;
@@ -823,7 +825,7 @@ bool CcdbApi::receiveObject(void* dataHolder, std::string const& path, std::map<
823825
long timestamp, std::map<std::string, std::string>* headers, std::string const& etag,
824826
const std::string& createdNotAfter, const std::string& createdNotBefore, bool followRedirect, CurlWriteCallback writeCallback) const
825827
{
826-
CURL* curlHandle;
828+
CurlHandle* curlHandle;
827829

828830
curlHandle = curl_easy_init();
829831
curl_easy_setopt(curlHandle, CURLOPT_USERAGENT, mUniqueAgentID.c_str());
@@ -843,7 +845,7 @@ bool CcdbApi::receiveObject(void* dataHolder, std::string const& path, std::map<
843845
curl_slist* option_list = nullptr;
844846
initCurlHTTPHeaderOptionsForRetrieve(curlHandle, option_list, timestamp, headers, etag, createdNotAfter, createdNotBefore, fullUrl);
845847

846-
curlResultCode = CURL_perform(curlHandle);
848+
curlResultCode = static_cast<CURLcode>(CURL_perform(curlHandle));
847849

848850
if (curlResultCode != CURLE_OK) {
849851
LOGP(alarm, "curl_easy_perform() failed: {}", curl_easy_strerror(curlResultCode));
@@ -1104,7 +1106,7 @@ void* CcdbApi::interpretAsTMemFileAndExtract(char* contentptr, size_t contentsiz
11041106
}
11051107

11061108
// navigate sequence of URLs until TFile content is found; object is extracted and returned
1107-
void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string const& url, std::type_info const& tinfo, std::map<std::string, std::string>* headers) const
1109+
void* CcdbApi::navigateURLsAndRetrieveContent(CurlHandle* curl_handle, std::string const& url, std::type_info const& tinfo, std::map<std::string, std::string>* headers) const
11081110
{
11091111
// a global internal data structure that can be filled with HTTP header information
11101112
// static --> to avoid frequent alloc/dealloc as optimization
@@ -1131,7 +1133,7 @@ void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string con
11311133

11321134
curlSetSSLOptions(curl_handle);
11331135

1134-
auto res = CURL_perform(curl_handle);
1136+
auto res = static_cast<CURLcode>(CURL_perform(curl_handle));
11351137
long response_code = -1;
11361138
void* content = nullptr;
11371139
bool errorflag = false;
@@ -1250,7 +1252,7 @@ void* CcdbApi::retrieveFromTFile(std::type_info const& tinfo, std::string const&
12501252

12511253
// normal mode follows
12521254

1253-
CURL* curl_handle = curl_easy_init();
1255+
CurlHandle* curl_handle = curl_easy_init();
12541256
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, mUniqueAgentID.c_str());
12551257
std::string fullUrl = getFullUrlForRetrieval(curl_handle, path, metadata, timestamp); // todo check if function still works correctly in case mInSnapshotMode
12561258
// 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
12991301

13001302
std::string CcdbApi::list(std::string const& path, bool latestOnly, std::string const& returnFormat, long createdNotAfter, long createdNotBefore) const
13011303
{
1302-
CURL* curl;
1304+
CurlHandle* curl;
13031305
CURLcode res = CURL_LAST;
13041306
std::string result;
13051307

@@ -1332,7 +1334,7 @@ std::string CcdbApi::list(std::string const& path, bool latestOnly, std::string
13321334
headers = appendGateToken(headers, fullUrl);
13331335
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
13341336

1335-
res = CURL_perform(curl);
1337+
res = static_cast<CURLcode>(CURL_perform(curl));
13361338
if (res != CURLE_OK) {
13371339
LOGP(alarm, "CURL_perform() failed: {}", curl_easy_strerror(res));
13381340
}
@@ -1353,7 +1355,7 @@ std::string CcdbApi::getTimestampString(long timestamp) const
13531355

13541356
void CcdbApi::deleteObject(std::string const& path, long timestamp) const
13551357
{
1356-
CURL* curl;
1358+
CurlHandle* curl;
13571359
CURLcode res;
13581360
long timestampLocal = timestamp == -1 ? getCurrentTimestamp() : timestamp;
13591361

@@ -1377,7 +1379,7 @@ void CcdbApi::deleteObject(std::string const& path, long timestamp) const
13771379
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
13781380

13791381
// Perform the request, res will get the return code
1380-
res = CURL_perform(curl);
1382+
res = static_cast<CURLcode>(CURL_perform(curl));
13811383
if (res != CURLE_OK) {
13821384
LOGP(alarm, "CURL_perform() failed: {}", curl_easy_strerror(res));
13831385
}
@@ -1391,7 +1393,7 @@ void CcdbApi::deleteObject(std::string const& path, long timestamp) const
13911393

13921394
void CcdbApi::truncate(std::string const& path) const
13931395
{
1394-
CURL* curl;
1396+
CurlHandle* curl;
13951397
CURLcode res;
13961398
for (size_t i = 0; i < hostsPool.size(); i++) {
13971399
// Declared inside the loop: a stringstream hoisted out of it accumulates,
@@ -1416,7 +1418,7 @@ void CcdbApi::truncate(std::string const& path) const
14161418
curlSetSSLOptions(curl);
14171419

14181420
// Perform the request, res will get the return code
1419-
res = CURL_perform(curl);
1421+
res = static_cast<CURLcode>(CURL_perform(curl));
14201422
if (res != CURLE_OK) {
14211423
LOGP(alarm, "CURL_perform() failed: {}", curl_easy_strerror(res));
14221424
}
@@ -1433,7 +1435,7 @@ size_t write_data(void*, size_t size, size_t nmemb, void*)
14331435

14341436
bool CcdbApi::isHostReachable() const
14351437
{
1436-
CURL* curl;
1438+
CurlHandle* curl;
14371439
CURLcode res = CURL_LAST;
14381440
bool result = false;
14391441

@@ -1455,7 +1457,7 @@ bool CcdbApi::isHostReachable() const
14551457
curl_easy_setopt(curl, CURLOPT_URL, mUrl.data());
14561458
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
14571459
curlSetSSLOptions(curl);
1458-
res = CURL_perform(curl);
1460+
res = static_cast<CURLcode>(CURL_perform(curl));
14591461
result = (res == CURLE_OK);
14601462
}
14611463

@@ -1561,7 +1563,7 @@ std::map<std::string, std::string> CcdbApi::retrieveHeaders(std::string const& p
15611563
{
15621564
// lambda that actually does the call to the CCDB server
15631565
auto do_remote_header_call = [this, &path, &metadata, timestamp]() -> std::map<std::string, std::string> {
1564-
CURL* curl = curl_easy_init();
1566+
CurlHandle* curl = curl_easy_init();
15651567
CURLcode res = CURL_LAST;
15661568
std::string fullUrl = getFullUrlForRetrieval(curl, path, metadata, timestamp);
15671569
std::map<std::string, std::string> headers;
@@ -1587,7 +1589,7 @@ std::map<std::string, std::string> CcdbApi::retrieveHeaders(std::string const& p
15871589
CURLcode getCodeRes = CURL_LAST;
15881590
for (size_t hostIndex = 0; hostIndex < hostsPool.size() && (httpCode >= 400 || res > 0 || getCodeRes > 0); hostIndex++) {
15891591
curl_easy_setopt(curl, CURLOPT_URL, fullUrl.c_str());
1590-
res = CURL_perform(curl);
1592+
res = static_cast<CURLcode>(CURL_perform(curl));
15911593
if (res != CURLE_OK && res != CURLE_UNSUPPORTED_PROTOCOL) {
15921594
// We take out the unsupported protocol error because we are only querying
15931595
// header info which is returned in any case. Unsupported protocol error
@@ -1747,7 +1749,7 @@ TClass* CcdbApi::tinfo2TClass(std::type_info const& tinfo)
17471749
int CcdbApi::updateMetadata(std::string const& path, std::map<std::string, std::string> const& metadata, long timestamp, std::string const& id, long newEOV)
17481750
{
17491751
int ret = -1;
1750-
CURL* curl = curl_easy_init();
1752+
CurlHandle* curl = curl_easy_init();
17511753
curl_easy_setopt(curl, CURLOPT_USERAGENT, mUniqueAgentID.c_str());
17521754
if (curl != nullptr) {
17531755
CURLcode res;
@@ -1788,7 +1790,7 @@ int CcdbApi::updateMetadata(std::string const& path, std::map<std::string, std::
17881790
curlSetSSLOptions(curl);
17891791

17901792
// Perform the request, res will get the return code
1791-
res = CURL_perform(curl);
1793+
res = static_cast<CURLcode>(CURL_perform(curl));
17921794
if (res != CURLE_OK) {
17931795
LOGP(alarm, "CURL_perform() failed: {}, code: {}", curl_easy_strerror(res), int(res));
17941796
ret = int(res);
@@ -1857,7 +1859,7 @@ void CcdbApi::scheduleDownload(RequestContext& requestContext, size_t* requestCo
18571859
return realsize;
18581860
};
18591861

1860-
CURL* curl_handle = curl_easy_init();
1862+
CurlHandle* curl_handle = curl_easy_init();
18611863
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, mUniqueAgentID.c_str());
18621864
std::string fullUrl = getFullUrlForRetrieval(curl_handle, requestContext.path, requestContext.metadata, requestContext.timestamp);
18631865

@@ -2269,12 +2271,12 @@ void CcdbApi::logReading(const std::string& path, long ts, const std::map<std::s
22692271
LOGP(info, "ccdb reads {}{}{} for {} ({}, agent_id: {}), ", mUrl, mUrl.back() == '/' ? "" : "/", upath, ts < 0 ? getCurrentTimestamp() : ts, comment, mUniqueAgentID);
22702272
}
22712273

2272-
void CcdbApi::asynchPerform(CURL* handle, size_t* requestCounter) const
2274+
void CcdbApi::asynchPerform(CurlHandle* handle, size_t* requestCounter) const
22732275
{
22742276
mDownloader->asynchSchedule(handle, requestCounter);
22752277
}
22762278

2277-
CURLcode CcdbApi::CURL_perform(CURL* handle) const
2279+
int CcdbApi::CURL_perform(CurlHandle* handle) const
22782280
{
22792281
if (mIsCCDBDownloaderPreferred) {
22802282
return mDownloader->perform(handle);

0 commit comments

Comments
 (0)