36 S3DownloadHandler(std::unique_ptr<XrdCl::File> file, XrdCl::ResponseHandler *handler, time_t timeout)
37 : m_expiry(time(NULL) + timeout), m_file(std::move(file)), m_handler(handler), m_buffer(new XrdCl::Buffer(kReadSize))
46 virtual ~S3DownloadHandler() noexcept = default;
48 virtual
void HandleResponse(XrdCl::XRootDStatus *status, XrdCl::AnyObject *response) override;
52 std::unique_ptr<XrdCl::
File> m_file;
53 XrdCl::ResponseHandler *m_handler;
54 std::unique_ptr<XrdCl::Buffer> m_buffer;
55 static constexpr
size_t kReadSize = 32 * 1024;
57 std::pair<time_t,
bool> GetTimeout()
const {
59 time_t now = time(NULL);
60 if (now >= m_expiry) {
63 return {m_expiry - now,
true};
66 class ReadHandler :
public XrdCl::ResponseHandler {
68 ReadHandler(std::unique_ptr<S3DownloadHandler>
parent) : m_parent(std::move(
parent)) {}
69 virtual ~ReadHandler() noexcept = default;
71 virtual
void HandleResponse(XrdCl::XRootDStatus *status, XrdCl::AnyObject *response) override;
74 std::unique_ptr<S3DownloadHandler> TakeParent() {
return std::move(m_parent); }
76 std::unique_ptr<S3DownloadHandler> m_parent;
79 class CloseHandler :
public XrdCl::ResponseHandler {
81 CloseHandler(std::unique_ptr<S3DownloadHandler>
parent, std::unique_ptr<XrdCl::XRootDStatus> status) : m_parent(std::move(
parent)), m_read_status(std::move(status)) {}
82 virtual ~CloseHandler() noexcept = default;
84 virtual
void HandleResponse(XrdCl::XRootDStatus *status, XrdCl::AnyObject *response) override;
87 std::unique_ptr<S3DownloadHandler> m_parent;
88 std::unique_ptr<XrdCl::XRootDStatus> m_read_status;
93S3DownloadHandler::HandleResponse(XrdCl::XRootDStatus *status_raw, XrdCl::AnyObject *response_raw)
95 std::unique_ptr<S3DownloadHandler> self(
this);
96 std::unique_ptr<XrdCl::XRootDStatus> status(status_raw);
97 std::unique_ptr<XrdCl::AnyObject> response(response_raw);
100 if (!status || !status->IsOK()) {
101 if (m_handler) m_handler->HandleResponse(status.release(), response.release());
104 auto [timeout, ok] = GetTimeout();
114 std::unique_ptr<ReadHandler> readHandler(
new ReadHandler(std::move(self)));
115 auto st = m_file->Read(0, S3DownloadHandler::kReadSize, m_buffer->GetBufferAtCursor(), readHandler.get(), timeout);
119 self = readHandler->TakeParent();
121 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(self), std::unique_ptr<XrdCl::XRootDStatus>(
new XrdCl::XRootDStatus(st))));
122 auto close_st = m_file->Close(closeHandler.get(), timeout);
123 if (close_st.IsOK()) {
124 closeHandler.release();
127 m_handler->HandleResponse(
new XrdCl::XRootDStatus(close_st),
nullptr);
134 readHandler.release();
138S3DownloadHandler::ReadHandler::HandleResponse(XrdCl::XRootDStatus *status_raw, XrdCl::AnyObject *response_raw) {
139 std::unique_ptr<ReadHandler> self(
this);
140 std::unique_ptr<XrdCl::XRootDStatus> status(status_raw);
141 std::unique_ptr<XrdCl::AnyObject> response(response_raw);
143 auto [timeout, ok] = m_parent->GetTimeout();
146 if (m_parent->m_handler) {
152 if (!status || !status->IsOK()) {
153 auto parent = m_parent.get();
154 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent), std::move(status)));
155 auto st =
parent->m_file->Close(closeHandler.get(), timeout);
157 closeHandler.release();
158 }
else if (
parent->m_handler) {
159 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(st),
nullptr);
164 XrdCl::ChunkInfo *chunkInfo =
nullptr;
165 response->Get(chunkInfo);
168 auto parent = m_parent.get();
169 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent),
171 auto st =
parent->m_file->Close(closeHandler.get(), timeout);
173 closeHandler.release();
174 }
else if (
parent->m_handler) {
175 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(st),
nullptr);
183 m_parent->m_buffer->ReAllocate(m_parent->m_buffer->GetCursor());
184 auto parent = m_parent.get();
185 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent),
nullptr));
186 auto st =
parent->m_file->Close(closeHandler.get(), timeout);
188 closeHandler.release();
189 }
else if (
parent->m_handler) {
190 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(st),
nullptr);
196 m_parent->m_buffer->AdvanceCursor(chunkInfo->
GetLength());
197 m_parent->m_buffer->ReAllocate(m_parent->m_buffer->GetCursor() + S3DownloadHandler::kReadSize);
199 auto st = m_parent->m_file->Read(m_parent->m_buffer->GetCursor(), kReadSize, m_parent->m_buffer->GetBufferAtCursor(), self.get(), timeout);
203 auto parent = m_parent.get();
204 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent),
nullptr));
205 auto close_st =
parent->m_file->Close(closeHandler.get(), timeout);
206 if (close_st.IsOK()) {
207 closeHandler.release();
208 }
else if (
parent->m_handler) {
209 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(close_st),
nullptr);
219S3DownloadHandler::CloseHandler::HandleResponse(XrdCl::XRootDStatus *status_raw, XrdCl::AnyObject *response_raw) {
220 std::unique_ptr<CloseHandler> self(
this);
221 std::unique_ptr<XrdCl::XRootDStatus> status(status_raw);
222 std::unique_ptr<XrdCl::AnyObject> response(response_raw);
227 if (m_parent->m_handler) {
228 m_parent->m_handler->HandleResponse(m_read_status.release(),
nullptr);
233 if (!status || !status->IsOK()) {
234 if (m_parent->m_handler) {
235 m_parent->m_handler->HandleResponse(status.release(),
nullptr);
241 response.reset(
new XrdCl::AnyObject());
242 response->Set(m_parent->m_buffer.release(),
true);
243 if (m_parent->m_handler) {
244 m_parent->m_handler->HandleResponse(status.release(), response.release());
253 std::unique_ptr<XrdCl::File> http_file(
new XrdCl::File(url));
255 if (header_callout) {
256 auto callout_loc =
reinterpret_cast<long long>(header_callout);
257 size_t buf_size = 16;
258 char callout_buf[buf_size];
259 std::to_chars_result result = std::to_chars(callout_buf, callout_buf + buf_size - 1, callout_loc, 16);
260 if (result.ec == std::errc{}) {
261 std::string callout_str(callout_buf, result.ptr - callout_buf);
262 http_file->SetProperty(
"XrdClHttpHeaderCallout", callout_str);
265 http_file->SetProperty(
"XrdClHttpFullDownload",
"true");
267 auto http_file_raw = http_file.get();
268 S3DownloadHandler *downloadHandler =
new S3DownloadHandler(std::move(http_file), handler, timeout);
static Env * GetEnv()
Get default client environment.
bool GetInt(const std::string &key, int &value)
Handle an async response.
XrdCl::XRootDStatus DownloadUrl(const std::string &url, XrdClHttp::HeaderCallout *header_callout, XrdCl::ResponseHandler *handler, time_t timeout)
const uint16_t errOperationExpired
const uint16_t stError
An error occurred that could potentially be retried.
const uint16_t errInternal
Internal error.
const int DefaultRequestTimeout
uint32_t GetLength() const
Get the data length.
@ Read
Open only for reading.