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;
73 std::unique_ptr<S3DownloadHandler> m_parent;
76 class CloseHandler : public XrdCl::ResponseHandler {
78 CloseHandler(std::unique_ptr<S3DownloadHandler>
parent, std::unique_ptr<XrdCl::XRootDStatus> status) : m_parent(std::move(
parent)), m_read_status(std::move(status)) {}
79 virtual ~CloseHandler() noexcept = default;
81 virtual
void HandleResponse(XrdCl::XRootDStatus *status, XrdCl::AnyObject *response) override;
84 std::unique_ptr<S3DownloadHandler> m_parent;
85 std::unique_ptr<XrdCl::XRootDStatus> m_read_status;
90S3DownloadHandler::HandleResponse(XrdCl::XRootDStatus *status_raw, XrdCl::AnyObject *response_raw)
92 std::unique_ptr<S3DownloadHandler> self(
this);
93 std::unique_ptr<XrdCl::XRootDStatus> status(status_raw);
94 std::unique_ptr<XrdCl::AnyObject> response(response_raw);
97 if (!status || !status->IsOK()) {
98 if (m_handler) m_handler->HandleResponse(status.release(), response.release());
101 auto [timeout, ok] = GetTimeout();
111 auto st = m_file->Read(0, S3DownloadHandler::kReadSize, m_buffer->GetBufferAtCursor(),
new ReadHandler(std::move(self)), timeout);
114 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(self), std::unique_ptr<XrdCl::XRootDStatus>(
new XrdCl::XRootDStatus(st))));
115 auto close_st = m_file->Close(closeHandler.get(), timeout);
116 if (close_st.IsOK()) {
117 closeHandler.release();
120 m_handler->HandleResponse(
new XrdCl::XRootDStatus(close_st),
nullptr);
128S3DownloadHandler::ReadHandler::HandleResponse(XrdCl::XRootDStatus *status_raw, XrdCl::AnyObject *response_raw) {
129 std::unique_ptr<ReadHandler> self(
this);
130 std::unique_ptr<XrdCl::XRootDStatus> status(status_raw);
131 std::unique_ptr<XrdCl::AnyObject> response(response_raw);
133 auto [timeout, ok] = m_parent->GetTimeout();
136 if (m_parent->m_handler) {
142 if (!status || !status->IsOK()) {
143 auto parent = m_parent.get();
144 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent), std::move(status)));
145 auto st =
parent->m_file->Close(closeHandler.get(), timeout);
147 closeHandler.release();
148 }
else if (
parent->m_handler) {
149 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(st),
nullptr);
154 XrdCl::ChunkInfo *chunkInfo =
nullptr;
155 response->Get(chunkInfo);
158 auto parent = m_parent.get();
159 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent),
161 auto st =
parent->m_file->Close(closeHandler.get(), timeout);
163 closeHandler.release();
164 }
else if (
parent->m_handler) {
165 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(st),
nullptr);
173 m_parent->m_buffer->ReAllocate(m_parent->m_buffer->GetCursor());
174 auto parent = m_parent.get();
175 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent),
nullptr));
176 auto st =
parent->m_file->Close(closeHandler.get(), timeout);
178 closeHandler.release();
179 }
else if (
parent->m_handler) {
180 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(st),
nullptr);
186 m_parent->m_buffer->AdvanceCursor(chunkInfo->
GetLength());
187 m_parent->m_buffer->ReAllocate(m_parent->m_buffer->GetCursor() + S3DownloadHandler::kReadSize);
188 auto st = m_parent->m_file->Read(m_parent->m_buffer->GetCursor(), kReadSize, m_parent->m_buffer->GetBufferAtCursor(), self.release(), timeout);
191 auto parent = m_parent.get();
192 std::unique_ptr<CloseHandler> closeHandler(
new CloseHandler(std::move(m_parent),
nullptr));
193 auto close_st =
parent->m_file->Close(closeHandler.get(), timeout);
194 if (close_st.IsOK()) {
195 closeHandler.release();
196 }
else if (
parent->m_handler) {
197 parent->m_handler->HandleResponse(
new XrdCl::XRootDStatus(close_st),
nullptr);
203S3DownloadHandler::CloseHandler::HandleResponse(XrdCl::XRootDStatus *status_raw, XrdCl::AnyObject *response_raw) {
204 std::unique_ptr<CloseHandler> self(
this);
205 std::unique_ptr<XrdCl::XRootDStatus> status(status_raw);
206 std::unique_ptr<XrdCl::AnyObject> response(response_raw);
211 if (m_parent->m_handler) {
212 m_parent->m_handler->HandleResponse(m_read_status.release(),
nullptr);
217 if (!status || !status->IsOK()) {
218 if (m_parent->m_handler) {
219 m_parent->m_handler->HandleResponse(status.release(),
nullptr);
225 response.reset(
new XrdCl::AnyObject());
226 response->Set(m_parent->m_buffer.release(),
true);
227 if (m_parent->m_handler) {
228 m_parent->m_handler->HandleResponse(status.release(), response.release());
237 std::unique_ptr<XrdCl::File> http_file(
new XrdCl::File());
242 if (!status.IsOK()) {
247 if (header_callout) {
248 auto callout_loc =
reinterpret_cast<long long>(header_callout);
249 size_t buf_size = 16;
250 char callout_buf[buf_size];
251 std::to_chars_result result = std::to_chars(callout_buf, callout_buf + buf_size - 1, callout_loc, 16);
252 if (result.ec == std::errc{}) {
253 std::string callout_str(callout_buf, result.ptr - callout_buf);
254 http_file->SetProperty(
"XrdClHttpHeaderCallout", callout_str);
257 http_file->SetProperty(
"XrdClHttpFullDownload",
"true");
259 auto http_file_raw = http_file.get();
260 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.