XRootD
XrdClHttpOpOpen.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* Copyright (C) 2025, Pelican Project, Morgridge Institute for Research */
3 /* */
4 /* This file is part of the XrdClHttp client plugin for XRootD. */
5 /* */
6 /* XRootD is free software: you can redistribute it and/or modify it under */
7 /* the terms of the GNU Lesser General Public License as published by the */
8 /* Free Software Foundation, either version 3 of the License, or (at your */
9 /* option) any later version. */
10 /* */
11 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
12 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
13 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
14 /* License for more details. */
15 /* */
16 /* The copyright holder's institutional names and contributor's names may not */
17 /* be used to endorse or promote products derived from this software without */
18 /* specific prior written permission of the institution or contributor. */
19 /******************************************************************************/
20 
21 #include "XrdClHttpFile.hh"
22 #include "XrdClHttpOps.hh"
23 #include "XrdClHttpResponseInfo.hh"
24 #include "XrdClHttpResponses.hh"
25 
26 #include <XrdCl/XrdClLog.hh>
27 
28 using namespace XrdClHttp;
29 
30 CurlOpenOp::CurlOpenOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout,
31  XrdCl::Log *logger, XrdClHttp::File *file, bool response_info, CreateConnCalloutType callout,
32  HeaderCallout *header_callout)
33 :
34  CurlStatOp(handler, url, timeout, logger, response_info, callout, header_callout),
35  m_file(file)
36 {}
37 
38 void
40 {
41  curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETFUNCTION, nullptr);
42  curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETDATA, nullptr);
43  curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTFUNCTION, nullptr);
44  curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTDATA, nullptr);
46 }
47 
48 void
49 CurlOpenOp::SetOpenProperties(bool setSize)
50 {
51  char *url = nullptr;
52  curl_easy_getinfo(m_curl.get(), CURLINFO_EFFECTIVE_URL, &url);
53  if (url && m_file) {
54  m_file->SetProperty("LastURL", url);
55  }
56 
57  if (setSize) {
58  auto [size, isdir] = GetStatInfo();
59  if (!isdir && size >= 0) {
60  m_file->SetProperty("XrdClHttpPrefetchSize", std::to_string(size));
61  }
62  }
63 
64  if (!m_headers.GetETag().empty())
65  {
66  std::string etag = m_headers.GetETag();
67  m_file->SetProperty("ETag", etag);
68  }
69  m_file->SetProperty("Cache-Control", m_headers.GetCacheControl());
70 }
71 
72 void
74 {
75  SetDone(false);
76  SetOpenProperties(true);
77  auto [size, isdir] = GetStatInfo();
78  if (isdir) {
79  m_logger->Error(kLogXrdClHttp, "Cannot open a directory");
80  Fail(XrdCl::errErrorResponse, kXR_isDirectory, "Cannot open a directory");
81  return;
82  }
83  if (size >= 0) {
84  m_file->SetProperty("ContentLength", std::to_string(size));
85  }
86  SuccessImpl(false);
87 }
88 
89 void
90 CurlOpenOp::Fail(uint16_t errCode, uint32_t errNum, const std::string &msg)
91 {
92  // Note: OpenFlags::New is equivalent to O_CREAT | O_EXCL; OpenFlags::Write is equivalent to O_WRONLY | O_CREAT;
93  // OpenFlags::Delete is equivalent to O_CREAT | O_TRUNC;
95  m_logger->Debug(kLogXrdClHttp, "CurlOpenOp succeeds as 404 was expected");
96  SetOpenProperties(false);
97  m_file->SetProperty("ContentLength", "0");
98  SuccessImpl(false);
99  return;
100  }
101  CurlOperation::Fail(errCode, errNum, msg);
102 }
103 
105 {
106  if (m_first_pause) {
107  m_first_pause = false;
108  } else {
110  return;
111  }
112 
113  // Set the various file-open properties. Note that we only invoke Pause() if the status code
114  // of the response is 200.
115  char *url = nullptr;
116  curl_easy_getinfo(m_curl.get(), CURLINFO_EFFECTIVE_URL, &url);
117  if (url) {
118  m_file.SetProperty("LastURL", url);
119  }
120 
121  auto length = m_headers.GetContentLength();
122  m_file.SetProperty("XrdClHttpPrefetchSize", std::to_string(length));
123 
124  if (!m_headers.GetETag().empty())
125  {
126  std::string etag = m_headers.GetETag();
127  m_file.SetProperty("ETag", etag);
128  }
129  m_file.SetProperty("Cache-Control", m_headers.GetCacheControl());
130 
132 }
@ kXR_NotFound
Definition: XProtocol.hh:1043
@ kXR_isDirectory
Definition: XProtocol.hh:1048
void ReleaseHandle() override
void Success() override
void Fail(uint16_t errCode, uint32_t errNum, const std::string &) override
CurlOpenOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *logger, XrdClHttp::File *file, bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout)
void SetDone(bool has_failed)
std::unique_ptr< CURL, void(*)(CURL *)> m_curl
virtual void Fail(uint16_t errCode, uint32_t errNum, const std::string &)
virtual void Pause() override
void ReleaseHandle() override
void SuccessImpl(bool returnObj)
std::pair< int64_t, bool > GetStatInfo()
XrdCl::OpenFlags::Flags Flags() const
virtual bool SetProperty(const std::string &name, const std::string &value) override
const std::string & GetETag() const
int64_t GetContentLength() const
const std::string & GetCacheControl() const
Handle diagnostics.
Definition: XrdClLog.hh:101
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition: XrdClLog.cc:231
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition: XrdClLog.cc:282
Handle an async response.
const uint16_t errErrorResponse
Definition: XrdClStatus.hh:105
ConnectionCallout *(*)(const std::string &, const ResponseInfo &) CreateConnCalloutType
const uint64_t kLogXrdClHttp
@ Write
Open only for writing.