All Classes Namespaces Functions Enumerations Enumerator Modules Pages
libcurl.hpp
1 /*
2  * Copyright (c) 2024-2025, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #ifndef KVIKIO_LIBCURL_FOUND
19 #error \
20  "cannot include the remote IO API, please build KvikIO with libcurl (-DKvikIO_REMOTE_SUPPORT=ON)"
21 #endif
22 
23 #include <functional>
24 #include <memory>
25 #include <mutex>
26 #include <sstream>
27 #include <string>
28 #include <vector>
29 
30 #include <curl/curl.h>
31 
32 #include <kvikio/error.hpp>
33 
34 namespace kvikio {
35 
53 class LibCurl {
54  public:
55  // We hold a unique pointer to the raw curl handle and set `curl_easy_cleanup` as its Deleter.
56  using UniqueHandlePtr = std::unique_ptr<CURL, std::function<decltype(curl_easy_cleanup)>>;
57 
58  private:
59  std::mutex _mutex{};
60  // Curl handles free to be used.
61  std::vector<UniqueHandlePtr> _free_curl_handles{};
62 
63  LibCurl();
64  ~LibCurl() noexcept;
65 
66  public:
67  static LibCurl& instance();
68 
72  UniqueHandlePtr get_free_handle();
73 
77  UniqueHandlePtr get_handle();
78 
82  void retain_handle(UniqueHandlePtr handle);
83 };
84 
91 class CurlHandle {
92  private:
93  char _errbuf[CURL_ERROR_SIZE];
94  LibCurl::UniqueHandlePtr _handle;
95 
96  public:
106  CurlHandle(LibCurl::UniqueHandlePtr handle, std::string source_file, std::string source_line);
107  ~CurlHandle() noexcept;
108 
112  CurlHandle(CurlHandle const&) = delete;
113  CurlHandle& operator=(CurlHandle const&) = delete;
114  CurlHandle(CurlHandle&& o) = delete;
115  CurlHandle& operator=(CurlHandle&& o) = delete;
116 
120  CURL* handle() noexcept;
121 
130  template <typename VAL>
131  void setopt(CURLoption option, VAL value)
132  {
133  CURLcode err = curl_easy_setopt(handle(), option, value);
134  if (err != CURLE_OK) {
135  std::stringstream ss;
136  ss << "curl_easy_setopt() error "
137  << "(" << curl_easy_strerror(err) << ")";
138  KVIKIO_FAIL(ss.str(), std::runtime_error);
139  }
140  }
141 
147  void perform();
148 
157  template <typename OUTPUT>
158  void getinfo(CURLINFO info, OUTPUT* output)
159  {
160  CURLcode err = curl_easy_getinfo(handle(), info, output);
161  if (err != CURLE_OK) {
162  std::stringstream ss;
163  ss << "curl_easy_getinfo() error "
164  << "(" << curl_easy_strerror(err) << ")";
165  KVIKIO_FAIL(ss.str(), std::runtime_error);
166  }
167  }
168 };
169 
170 namespace detail {
185 __attribute__((noinline)) inline std::string fix_conda_file_path_hack(std::string filename)
186 {
187  if (filename.data() != nullptr) { return std::string{filename.data()}; }
188  return std::string{};
189 }
190 } // namespace detail
191 
197 #define create_curl_handle() \
198  kvikio::CurlHandle(kvikio::LibCurl::instance().get_handle(), \
199  kvikio::detail::fix_conda_file_path_hack(__FILE__), \
200  KVIKIO_STRINGIFY(__LINE__))
201 
202 } // namespace kvikio
Representation of a curl easy handle pointer and its operations.
Definition: libcurl.hpp:91
void setopt(CURLoption option, VAL value)
Set option for the curl handle.
Definition: libcurl.hpp:131
CurlHandle(LibCurl::UniqueHandlePtr handle, std::string source_file, std::string source_line)
Construct a new curl handle.
void getinfo(CURLINFO info, OUTPUT *output)
Extract information from a curl handle.
Definition: libcurl.hpp:158
void perform()
Perform a blocking network transfer using previously set options.
CURL * handle() noexcept
Get the underlying curl easy handle pointer.
Singleton class to initialize and cleanup the global state of libcurl.
Definition: libcurl.hpp:53
UniqueHandlePtr get_free_handle()
Returns a free curl handle if available.
void retain_handle(UniqueHandlePtr handle)
Retain a curl handle for later use.
UniqueHandlePtr get_handle()
Returns a curl handle, create a new handle if none is available.
#define KVIKIO_FAIL(...)
Indicates that an erroneous code path has been taken.
Definition: error.hpp:252
KvikIO namespace.
Definition: batch.hpp:27