Project
Loading...
Searching...
No Matches
CCDBDownloader.h
Go to the documentation of this file.
1// Copyright 2019-2023 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#ifndef O2_CCDBDOWNLOADER_H_
12#define O2_CCDBDOWNLOADER_H_
13
14#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
16#endif
17
18#include <cstdio>
19#include <cstdlib>
20#include <curl/curl.h>
21#include <string>
22#include <vector>
23#include <iostream>
24#include <thread>
25#include <mutex>
26#include <condition_variable>
27#include <unordered_map>
28#include <map>
29#include <functional>
30
31typedef struct uv_loop_s uv_loop_t;
32typedef struct uv_timer_s uv_timer_t;
33typedef struct uv_poll_s uv_poll_t;
34typedef struct uv_signal_s uv_signal_t;
35typedef struct uv_async_s uv_async_t;
36typedef struct uv_handle_s uv_handle_t;
37
38namespace o2::ccdb
39{
40
41#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
43 std::multimap<std::string, std::string> header;
44 o2::pmr::vector<char>* object = nullptr;
45 int counter = 0;
46};
47
48typedef struct DownloaderRequestData {
49 std::vector<std::string> hosts;
50 std::string path;
53 std::map<std::string, std::string>* headers;
54 std::string userAgent;
55 curl_slist* optionsList;
56
57 std::function<bool(std::string)> localContentCallback;
58} DownloaderRequestData;
59#endif
60
61/*
62 Some functions below aren't member functions of CCDBDownloader because both curl and libuv require callback functions which have to be either static or non-member.
63 Because non-static functions are used in the functions below, they must be non-member.
64*/
65
72void closeHandles(uv_handle_t* handle, void* arg);
73
81curl_socket_t opensocketCallback(void* clientp, curlsocktype purpose, struct curl_sockaddr* address);
82
88void onUVClose(uv_handle_t* handle);
89
94
103{
104 public:
109 std::unordered_map<curl_socket_t, uv_timer_t*> mSocketTimerMap;
110
115
119 std::unordered_map<uv_handle_t*, bool> mHandleMap;
120
125
130
134 int mRequestTimeoutMS = 300000;
135
140
145
150
151 CCDBDownloader(uv_loop_t* uv_loop = nullptr);
153
159 CURLcode perform(CURL* handle);
160
165 std::vector<CURLcode> batchBlockingPerform(std::vector<CURL*> const& handleVector);
166
173 void asynchSchedule(CURL* handle, size_t* requestCounter);
174
178 void setMaxParallelConnections(int limit);
179
183 void setKeepaliveTimeoutTime(int timeoutMS);
184
188 void setConnectionTimeoutTime(int timeoutMS);
189
193 void setRequestTimeoutTime(int timeoutMS);
194
198 void setHappyEyeballsHeadstartTime(int headstartMS);
199
204
209
215 void runLoop(bool noWait);
216
220 std::string prepareLogMessage(std::string host_url, std::string userAgent, const std::string& path, long ts, const std::map<std::string, std::string>* headers, long httpCode) const;
221
225 std::string trimHostUrl(std::string full_host_url) const;
226
227 private:
231 std::string prepareRedirectedURL(std::string address, std::string potentialHost) const;
232
239 std::vector<std::string> getLocations(std::multimap<std::string, std::string>* headerMap) const;
240
241 std::string mUserAgentId = "CCDBDownloader";
245 void setupInternalUVLoop();
246
250 int mHandlesInUse = 0;
251
255 CURLM* mCurlMultiHandle = nullptr;
256
260 uv_timer_t* mTimeoutTimer;
261
265 std::vector<CURL*> mHandlesToBeAdded;
266
270 enum RequestType {
271 BLOCKING,
272 ASYNCHRONOUS
273 };
274
278 typedef struct curl_context_s {
279 uv_poll_t* poll_handle;
280 curl_socket_t sockfd = -1;
281 CCDBDownloader* CD = nullptr;
282 } curl_context_t;
283
287 typedef struct DataForSocket {
288 CCDBDownloader* CD;
289 CURLM* curlm;
290 } DataForSocket;
291
292 DataForSocket mSocketData;
293
294#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
298 typedef struct PerformData {
299 CURLcode* codeDestination;
300 size_t* requestsLeft;
301 RequestType type;
302 int hostInd;
303 int locInd;
304 DownloaderRequestData* requestData;
305 curl_slist** options;
306 } PerformData;
307#endif
308
315 static void closesocketCallback(void* clientp, curl_socket_t item);
316
317#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
318 // Returns a new location string or an empty string if all locations under current host have been accessedd
319 std::string getNewLocation(PerformData* performData, std::vector<std::string>& locations) const;
320
321 // Reschedules the transfer to be performed with a different host.
322 void tryNewHost(PerformData* performData, CURL* easy_handle);
323
324 // Retrieves content from either alien, cvmfs or local storage using a callback to CCDBApi.
325 void getLocalContent(PerformData* performData, std::string& newLocation, bool& contentRetrieved, std::vector<std::string>& locations);
326
327 // Continues a transfer via a http redirect.
328 void httpRedirect(PerformData* performData, std::string& newLocation, CURL* easy_handle);
329
330 // Continues a transfer via a redirect. The redirect can point to a local file, alien file or a http address.
331 void followRedirect(PerformData* performData, CURL* easy_handle, std::vector<std::string>& locations, bool& rescheduled, bool& contentRetrieved);
332#endif
333
341 static void curlPerform(uv_poll_t* handle, int status, int events);
342
346 static int handleSocket(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp);
347
353 static void closeSocketByTimer(uv_timer_t* handle);
354
360 static void curlTimeout(uv_timer_t* req);
361
367 static void curlCloseCB(uv_handle_t* handle);
368
374 static void destroyCurlContext(curl_context_t* context);
375
383 static int startTimeout(CURLM* multi, long timeout_ms, void* userp);
384
388 void initializeMultiHandle();
389
396 void transferFinished(CURL* handle, CURLcode curlCode);
397
401 void checkMultiInfo();
402
403#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
407 void setHandleOptions(CURL* handle, PerformData* data);
408#endif
409
415 curl_context_t* createCurlContext(curl_socket_t sockfd);
416
420 void checkHandleQueue();
421};
422
426typedef struct DataForClosingSocket {
428 curl_socket_t socket;
429} DataForClosingSocket;
430
431} // namespace o2::ccdb
432
433#endif // O2_CCDB_CCDBDOWNLOADER_H
struct uv_timer_s uv_timer_t
struct uv_signal_s uv_signal_t
struct uv_async_s uv_async_t
struct uv_handle_s uv_handle_t
struct uv_poll_s uv_poll_t
struct uv_loop_s uv_loop_t
void setRequestTimeoutTime(int timeoutMS)
CURLcode perform(CURL *handle)
void asynchSchedule(CURL *handle, size_t *requestCounter)
std::string trimHostUrl(std::string full_host_url) const
void setKeepaliveTimeoutTime(int timeoutMS)
std::vector< CURLcode > batchBlockingPerform(std::vector< CURL * > const &handleVector)
void setConnectionTimeoutTime(int timeoutMS)
void setHappyEyeballsHeadstartTime(int headstartMS)
std::string prepareLogMessage(std::string host_url, std::string userAgent, const std::string &path, long ts, const std::map< std::string, std::string > *headers, long httpCode) const
std::unordered_map< uv_handle_t *, bool > mHandleMap
std::unordered_map< curl_socket_t, uv_timer_t * > mSocketTimerMap
void setMaxParallelConnections(int limit)
GLuint const GLint * locations
Definition glcorearb.h:5740
GLuint GLuint64EXT address
Definition glcorearb.h:5846
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLuint counter
Definition glcorearb.h:3987
information complementary to a CCDB object (path, metadata, startTimeValidity, endTimeValidity etc)
void closeHandles(uv_handle_t *handle, void *arg)
curl_socket_t opensocketCallback(void *clientp, curlsocktype purpose, struct curl_sockaddr *address)
void onUVClose(uv_handle_t *handle)
std::vector< T, o2::pmr::polymorphic_allocator< T > > vector
std::function< bool(std::string)> localContentCallback
std::vector< std::string > hosts
std::map< std::string, std::string > * headers
std::multimap< std::string, std::string > header