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::vector<std::string> locations;
51 std::string path;
54 std::map<std::string, std::string>* headers;
55 std::string userAgent;
56 // One header list per entry of `hosts`, parallel to it. Per host and not one
57 // shared list because the gate token a broker expects is per endpoint: a
58 // multi-host pool can mix them, and tryNewHost() swapping only the URL left
59 // the second host receiving the first host's token -- answered 401, so the
60 // failover silently retrieved nothing (testCcdbApi multi_host_test).
61 std::vector<curl_slist*> optionsLists;
62
63 std::function<bool(std::string)> localContentCallback;
64} DownloaderRequestData;
65#endif
66
67/*
68 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.
69 Because non-static functions are used in the functions below, they must be non-member.
70*/
71
78void closeHandles(uv_handle_t* handle, void* arg);
79
87curl_socket_t opensocketCallback(void* clientp, curlsocktype purpose, struct curl_sockaddr* address);
88
94void onUVClose(uv_handle_t* handle);
95
100
109{
110 public:
115 std::unordered_map<curl_socket_t, uv_timer_t*> mSocketTimerMap;
116
121
125 std::unordered_map<uv_handle_t*, bool> mHandleMap;
126
131
136
140 int mRequestTimeoutMS = 300000;
141
146
151
156
157 CCDBDownloader(uv_loop_t* uv_loop = nullptr);
159
165 CURLcode perform(CURL* handle);
166
171 std::vector<CURLcode> batchBlockingPerform(std::vector<CURL*> const& handleVector);
172
179 void asynchSchedule(CURL* handle, size_t* requestCounter);
180
184 void setMaxParallelConnections(int limit);
185
189 void setKeepaliveTimeoutTime(int timeoutMS);
190
194 void setConnectionTimeoutTime(int timeoutMS);
195
199 void setRequestTimeoutTime(int timeoutMS);
200
204 void setHappyEyeballsHeadstartTime(int headstartMS);
205
210
215
221 void runLoop(bool noWait);
222
226 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;
227
231 std::string trimHostUrl(std::string full_host_url) const;
232
233 private:
237 std::string prepareRedirectedURL(std::string address, std::string potentialHost) const;
238
246 void updateLocations(std::multimap<std::string, std::string>* headerMap, std::vector<std::string>* locations, int* locIndex) const;
247
248 std::string mUserAgentId = "CCDBDownloader";
252 void setupInternalUVLoop();
253
257 int mHandlesInUse = 0;
258
262 CURLM* mCurlMultiHandle = nullptr;
263
267 uv_timer_t* mTimeoutTimer;
268
272 std::vector<CURL*> mHandlesToBeAdded;
273
277 enum RequestType {
278 BLOCKING,
279 ASYNCHRONOUS
280 };
281
285 typedef struct curl_context_s {
286 uv_poll_t* poll_handle;
287 curl_socket_t sockfd = -1;
288 CCDBDownloader* CD = nullptr;
289 } curl_context_t;
290
294 typedef struct DataForSocket {
295 CCDBDownloader* CD;
296 CURLM* curlm;
297 } DataForSocket;
298
299 DataForSocket mSocketData;
300
301#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
305 typedef struct PerformData {
306 CURLcode* codeDestination;
307 size_t* requestsLeft;
308 RequestType type;
309 int hostInd;
310 int locInd;
311 DownloaderRequestData* requestData;
312 // Freed by transferFinished; indexed by hostInd, see DownloaderRequestData.
313 std::vector<curl_slist*>* options;
314 } PerformData;
315#endif
316
323 static void closesocketCallback(void* clientp, curl_socket_t item);
324
325#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
326 // Returns a new location string or an empty string if all locations under current host have been accessedd
327 std::string getNewLocation(PerformData* performData, std::vector<std::string>& locations) const;
328
329 // Reschedules the transfer to be performed with a different host.
330 void tryNewHost(PerformData* performData, CURL* easy_handle);
331
332 // Retrieves content from either alien, cvmfs or local storage using a callback to CCDBApi.
333 void getLocalContent(PerformData* performData, std::string& newLocation, bool& contentRetrieved, std::vector<std::string>& locations);
334
335 // Continues a transfer via a http redirect.
336 void httpRedirect(PerformData* performData, std::string& newLocation, CURL* easy_handle);
337
338 // Continues a transfer via a redirect. The redirect can point to a local file, alien file or a http address.
339 void followRedirect(PerformData* performData, CURL* easy_handle, std::vector<std::string>& locations, bool& rescheduled, bool& contentRetrieved);
340#endif
341
349 static void curlPerform(uv_poll_t* handle, int status, int events);
350
354 static int handleSocket(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp);
355
361 static void closeSocketByTimer(uv_timer_t* handle);
362
368 static void curlTimeout(uv_timer_t* req);
369
375 static void curlCloseCB(uv_handle_t* handle);
376
382 static void destroyCurlContext(curl_context_t* context);
383
391 static int startTimeout(CURLM* multi, long timeout_ms, void* userp);
392
396 void initializeMultiHandle();
397
404 void transferFinished(CURL* handle, CURLcode curlCode);
405
409 void checkMultiInfo();
410
411#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__)
415 void setHandleOptions(CURL* handle, PerformData* data);
416#endif
417
423 curl_context_t* createCurlContext(curl_socket_t sockfd);
424
428 void checkHandleQueue();
429};
430
434typedef struct DataForClosingSocket {
436 curl_socket_t socket;
437} DataForClosingSocket;
438
439} // namespace o2::ccdb
440
441#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, fair::mq::pmr::polymorphic_allocator< T > > vector
std::function< bool(std::string)> localContentCallback
std::vector< curl_slist * > optionsLists
std::vector< std::string > locations
std::vector< std::string > hosts
std::map< std::string, std::string > * headers
std::multimap< std::string, std::string > header