XRootD
Loading...
Searching...
No Matches
XrdClHttp::CurlOperation Class Referenceabstract

#include <XrdClHttpOps.hh>

Inheritance diagram for XrdClHttp::CurlOperation:
Collaboration diagram for XrdClHttp::CurlOperation:

Public Types

using HeaderList = std::vector<std::pair<std::string, std::string>>
using HttpVerb = XrdClHttp::HttpVerb
enum  OpError {
  ErrNone ,
  ErrHeaderTimeout ,
  ErrCallback ,
  ErrOperationTimeout ,
  ErrTransferClientStall ,
  ErrTransferStall ,
  ErrTransferSlow
}
enum class  RedirectAction {
  Fail ,
  Reinvoke ,
  ReinvokeAfterAllow
}

Public Member Functions

 CurlOperation (const CurlOperation &)=delete
 CurlOperation (XrdCl::ResponseHandler *handler, const std::string &url, std::chrono::steady_clock::time_point expiry, XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout)
 CurlOperation (XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout)
virtual ~CurlOperation ()
virtual bool ContinueHandle ()
void ExtendDeadline (struct timespec timeout)
virtual void Fail (uint16_t errCode, uint32_t errNum, const std::string &)
bool FinishSetup (CURL *curl)
std::pair< XErrorCode, std::string > GetCallbackError () const
CreateConnCalloutType GetConnCalloutFunc () const
std::string GetCurlErrorMessage () const
CURL * GetCurlHandle () const
OpError GetError () const
std::chrono::steady_clock::time_point GetHeaderExpiry () const
std::chrono::steady_clock::time_point GetOperationExpiry ()
std::unique_ptr< ResponseInfo > GetResponseInfo ()
int GetStatusCode () const
std::string GetStatusMessage () const
bool GetTriedBoker () const
const std::string & GetUrl () const
virtual HttpVerb GetVerb () const =0
bool HasFailed () const
bool HeaderTimeoutExpired (const std::chrono::steady_clock::time_point &now)
bool IsDone () const
bool IsPaused () const
bool IsRedirect () const
std::unique_ptr< ResponseInfo > MoveResponseInfo ()
bool OperationTimeoutExpired (const std::chrono::steady_clock::time_point &now)
virtual void OptionsDone ()
virtual RedirectAction Redirect (std::string &target)
virtual void ReleaseHandle ()
virtual bool RequiresOptions () const
virtual void SetContinueQueue (std::shared_ptr< XrdClHttp::HandlerQueue > queue)
void SetTriedBoker ()
virtual bool Setup (CURL *curl, CurlWorker &)
bool StartConnectionCallout (std::string &err)
std::tuple< uint64_t, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration > StatisticsReset ()
virtual void Success ()=0
bool TransferStalled (uint64_t xfer_bytes, const std::chrono::steady_clock::time_point &now)
bool UseConnectionCallout ()
virtual int WaitSocket ()
virtual int WaitSocketCallback (std::string &err)

Static Public Member Functions

static void CleanupDnsCache ()
static int GetDefaultSlowRateBytesSec ()
static int GetDefaultStallTimeout ()
static const std::string GetVerbString (HttpVerb)
static void SetSlowRateBytesSec (int rate)
static void SetStallTimeout (const std::chrono::steady_clock::duration &stall_interval)
static void SetStallTimeout (int stall_interval)

Protected Member Functions

int FailCallback (XErrorCode ecode, const std::string &emsg)
void SetDone (bool has_failed)
void SetPaused (bool paused)
bool SetupNextRequest (const std::string &url, CurlWorker &worker)
void UpdateBytes (uint64_t bytes)

Protected Attributes

std::unique_ptr< CURL, void(*)(CURL *)> m_curl
XrdCl::ResponseHandler * m_handler {nullptr}
HeaderCallout * m_header_callout
std::atomic< std::chrono::steady_clock::time_point > m_header_expiry
HeaderParser m_headers
std::vector< std::pair< std::string, std::string > > m_headers_list
XrdCl::Log * m_logger
int m_minimum_rate {m_minimum_transfer_rate}
std::chrono::steady_clock::time_point m_operation_expiry
std::string m_request_url
const std::string m_url

Static Protected Attributes

static constexpr int m_default_minimum_rate {1024 * 256}
static int m_minimum_transfer_rate {CurlOperation::m_default_minimum_rate}

Detailed Description

Definition at line 60 of file XrdClHttpOps.hh.

Member Typedef Documentation

◆ HeaderList

using XrdClHttp::CurlOperation::HeaderList = std::vector<std::pair<std::string, std::string>>

Definition at line 62 of file XrdClHttpOps.hh.

◆ HttpVerb

Member Enumeration Documentation

◆ OpError

Enumerator
ErrNone 
ErrHeaderTimeout 
ErrCallback 
ErrOperationTimeout 
ErrTransferClientStall 
ErrTransferStall 
ErrTransferSlow 

Definition at line 216 of file XrdClHttpOps.hh.

216 {
217 ErrNone, // No error
218 ErrHeaderTimeout, // Header was not sent back in time
219 ErrCallback, // Error in the read/write callback (e.g., response too large for propfind)
220 ErrOperationTimeout, // Entire curl request operation has timed out
221 ErrTransferClientStall, // Transfer stalled while client had paused it (no data was available)
222 ErrTransferStall, // Transfer has stalled, not receiving any data within 60 seconds
223 ErrTransferSlow, // Average transfer rate is below the minimum
224 };

◆ RedirectAction

Enumerator
Fail 
Reinvoke 
ReinvokeAfterAllow 

Definition at line 145 of file XrdClHttpOps.hh.

145 {
146 Fail, // The redirect parsing failed and Fail() was called
147 Reinvoke, // Reinvoke the curl handle, following redirect
148 ReinvokeAfterAllow, // Reinvoke the Redirect function once the allowed verbs are known.
149 };

Constructor & Destructor Documentation

◆ CurlOperation() [1/3]

CurlOperation::CurlOperation ( XrdCl::ResponseHandler * handler,
const std::string & url,
struct timespec timeout,
XrdCl::Log * log,
CreateConnCalloutType callout,
HeaderCallout * header_callout )

Definition at line 168 of file XrdClHttpOps.cc.

170 :
171 CurlOperation::CurlOperation(handler, url, CalculateExpiry(timeout), logger, callout, header_callout)
172 {}
std::chrono::steady_clock::time_point CalculateExpiry(struct timespec timeout)
CurlOperation(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout)

References CurlOperation(), and CalculateExpiry().

Referenced by XrdClHttp::CurlCopyOp::CurlCopyOp(), XrdClHttp::CurlDeleteOp::CurlDeleteOp(), XrdClHttp::CurlListdirOp::CurlListdirOp(), XrdClHttp::CurlMkcolOp::CurlMkcolOp(), CurlOperation(), CurlOperation(), XrdClHttp::CurlOptionsOp::CurlOptionsOp(), XrdClHttp::CurlPutOp::CurlPutOp(), XrdClHttp::CurlPutOp::CurlPutOp(), XrdClHttp::CurlReadOp::CurlReadOp(), XrdClHttp::CurlStatOp::CurlStatOp(), XrdClHttp::CurlTapeOp::CurlTapeOp(), and XrdClHttp::CurlVectorReadOp::CurlVectorReadOp().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CurlOperation() [2/3]

CurlOperation::CurlOperation ( XrdCl::ResponseHandler * handler,
const std::string & url,
std::chrono::steady_clock::time_point expiry,
XrdCl::Log * log,
CreateConnCalloutType callout,
HeaderCallout * header_callout )

Definition at line 174 of file XrdClHttpOps.cc.

176 :
177 m_header_expiry(expiry),
178 m_header_callout(header_callout),
179 m_last_reset(std::chrono::steady_clock::now()),
180 m_last_header_reset(m_last_reset),
181 m_start_op(m_last_reset),
182 m_header_start(m_last_reset),
183 m_conn_callout(callout),
184 m_url(DavToHttp(url)),
186 m_handler(handler),
187 m_curl(nullptr, &curl_easy_cleanup),
188 m_logger(logger)
189 {}
std::atomic< std::chrono::steady_clock::time_point > m_header_expiry
const std::string m_url
std::unique_ptr< CURL, void(*)(CURL *)> m_curl
HeaderCallout * m_header_callout
XrdCl::ResponseHandler * m_handler

References m_curl, m_handler, m_header_callout, m_header_expiry, m_logger, m_request_url, and m_url.

◆ ~CurlOperation()

CurlOperation::~CurlOperation ( )
virtual

Definition at line 191 of file XrdClHttpOps.cc.

191{}

◆ CurlOperation() [3/3]

XrdClHttp::CurlOperation::CurlOperation ( const CurlOperation & )
delete

References CurlOperation(), Fail(), FinishSetup(), ReleaseHandle(), and Setup().

Here is the call graph for this function:

Member Function Documentation

◆ CleanupDnsCache()

void CurlOperation::CleanupDnsCache ( )
static

Definition at line 780 of file XrdClHttpOps.cc.

781{
782 auto now = std::chrono::steady_clock::now();
783 for (auto it = fake_dns_refcount.begin(); it != fake_dns_refcount.end(); ) {
784 if (it->second->count <= 0 && it->second->IsExpired(now)) {
785 auto rev_iter = reverse_fake_dns_map.find(*it->first);
786 if (rev_iter != reverse_fake_dns_map.end()) {
787 fake_dns_map.erase(rev_iter->second.first);
788 reverse_fake_dns_map.erase(rev_iter);
789 }
790 it = fake_dns_refcount.erase(it);
791 } else {
792 ++it;
793 }
794 }
795}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ ContinueHandle()

virtual bool XrdClHttp::CurlOperation::ContinueHandle ( )
inlinevirtual

Reimplemented in XrdClHttp::CurlPutOp, and XrdClHttp::CurlReadOp.

Definition at line 139 of file XrdClHttpOps.hh.

139{return true;}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ ExtendDeadline()

void CurlOperation::ExtendDeadline ( struct timespec timeout)

Definition at line 194 of file XrdClHttpOps.cc.

195{
196 auto expiry = CalculateExpiry(timeout);
197 auto current = m_header_expiry.load(std::memory_order_relaxed);
198 while (expiry > current &&
199 !m_header_expiry.compare_exchange_weak(current, expiry,
200 std::memory_order_relaxed))
201 ;
202}

References CalculateExpiry(), and m_header_expiry.

Here is the call graph for this function:

◆ Fail()

void CurlOperation::Fail ( uint16_t errCode,
uint32_t errNum,
const std::string & msg )
virtual

Reimplemented in XrdClHttp::CurlMkcolOp, XrdClHttp::CurlOpenOp, XrdClHttp::CurlOptionsOp, XrdClHttp::CurlPutOp, XrdClHttp::CurlReadOp, XrdClHttp::CurlTapeOp, and XrdClHttp::CurlVectorReadOp.

Definition at line 205 of file XrdClHttpOps.cc.

206{
207 SetDone(true);
208 if (m_handler == nullptr) {return;}
209 if (!msg.empty()) {
210 m_logger->Debug(kLogXrdClHttp, "curl operation failed with message: %s", msg.c_str());
211 } else {
212 m_logger->Debug(kLogXrdClHttp, "curl operation failed with status code %d", errNum);
213 }
214 auto status = new XrdCl::XRootDStatus(XrdCl::stError, errCode, errNum, msg);
215 auto handle = m_handler;
216 m_handler = nullptr;
217 handle->HandleResponse(status, nullptr);
218}
void SetDone(bool has_failed)
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition XrdClLog.cc:282
virtual void HandleResponse(XRootDStatus *status, AnyObject *response)
const uint64_t kLogXrdClHttp
const uint16_t stError
An error occurred that could potentially be retried.

References XrdCl::Log::Debug(), XrdCl::ResponseHandler::HandleResponse(), XrdClHttp::kLogXrdClHttp, m_handler, m_logger, SetDone(), and XrdCl::stError.

Referenced by CurlOperation(), FinishSetup(), Redirect(), XrdClHttp::CurlWorker::Run(), StartConnectionCallout(), XrdClHttp::CurlListdirOp::Success(), XrdClHttp::CurlQueryOp::Success(), and XrdClHttp::CurlStatOp::SuccessImpl().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ FailCallback()

int CurlOperation::FailCallback ( XErrorCode ecode,
const std::string & emsg )
protected

Definition at line 221 of file XrdClHttpOps.cc.

221 {
222 m_callback_error_code = ecode;
223 m_callback_error_str = emsg;
224 m_error = OpError::ErrCallback;
225 m_logger->Debug(kLogXrdClHttp, "%s", emsg.c_str());
226 return 0;
227}
int emsg(int rc, char *msg)

References XrdCl::Log::Debug(), emsg(), ErrCallback, XrdClHttp::kLogXrdClHttp, and m_logger.

Referenced by XrdClHttp::CurlVectorReadOp::Write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ FinishSetup()

bool CurlOperation::FinishSetup ( CURL * curl)

Definition at line 230 of file XrdClHttpOps.cc.

231{
232 if(m_parsed_url)
233 {
235 }
236
237 // The client asks every request to carry the headers given by the HttpHeaders
238 // environment setting. HeaderBuilder interprets the contents.
239 std::string spec;
240 if (auto env = XrdCl::DefaultEnv::GetEnv()) {
241 env->GetString("HttpHeaders", spec);
242 }
243
244 if (!spec.empty()) {
245 // Refuse to send anything when the requested headers could not be understood;
246 // quietly omitting them changes what the request asks for.
247 //
248 // Fail here rather than leaving it to the caller, whose failure message for a
249 // setup error would suggest the wrong cause entirely.
250 HeaderList requested;
251 if (!HeaderBuilder::Build(spec, requested)) {
252 m_logger->Error(kLogXrdClHttp, "Not sending request to %s: the requested"
253 " headers could not be used", m_url.c_str());
254 Fail(XrdCl::errInvalidArgs, EINVAL, "Invalid header requested");
255 return false;
256 }
258 }
259
260 if (!m_header_callout) {
261 m_header_slist.reset();
262 for (const auto &header : m_headers_list) {
263 m_header_slist.reset(curl_slist_append(m_header_slist.release(),
264 (header.first + ": " + header.second).c_str()));
265 }
266 return curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_header_slist.get()) == CURLE_OK;
267 }
268 const auto &verb = GetVerbString(GetVerb());
269
270 auto extra_headers = m_header_callout->GetHeaders(
272 if (!extra_headers) {
274 "Failed to get headers from header callout for %s",
275 m_request_url.c_str());
276 return false;
277 }
278 m_header_slist.reset();
279 for (const auto &header : *extra_headers) {
280 if (HeaderBuilder::CompareIgnoreCase(header.first, "Content-Length")) {
281 auto upload_size = std::stoull(header.second);
282 curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, upload_size);
283 continue;
284 }
285 m_header_slist.reset(curl_slist_append(m_header_slist.release(),
286 (header.first + ": " + header.second).c_str()));
287 }
288 return curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_header_slist.get()) == CURLE_OK;
289}
static const std::string GetVerbString(HttpVerb)
virtual HttpVerb GetVerb() const =0
std::vector< std::pair< std::string, std::string > > HeaderList
std::vector< std::pair< std::string, std::string > > m_headers_list
virtual void Fail(uint16_t errCode, uint32_t errNum, const std::string &)
virtual std::shared_ptr< HeaderList > GetHeaders(const std::string &verb, const std::string &url, const HeaderList &headers)=0
static Env * GetEnv()
Get default client environment.
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition XrdClLog.cc:231
bool CompareIgnoreCase(const std::string_view lhs, const std::string_view rhs)
void AppendMissing(const HeaderList &extra, HeaderList &headers)
bool Build(const std::string_view spec, HeaderList &headers)
void InjectBearerToken(const XrdCl::URL &url, std::vector< std::pair< std::string, std::string > > &headers, XrdCl::Log *logger=nullptr)
const uint16_t errInvalidArgs

References XrdClHttp::HeaderBuilder::AppendMissing(), XrdClHttp::HeaderBuilder::Build(), XrdClHttp::HeaderBuilder::CompareIgnoreCase(), XrdCl::errInvalidArgs, XrdCl::Log::Error(), Fail(), XrdCl::DefaultEnv::GetEnv(), XrdClHttp::HeaderCallout::GetHeaders(), GetVerb(), GetVerbString(), XrdClHttp::InjectBearerToken(), XrdClHttp::kLogXrdClHttp, m_header_callout, m_headers_list, m_logger, m_request_url, and m_url.

Referenced by CurlOperation(), XrdClHttp::CurlWorker::Run(), and XrdClHttp::CurlTapeOp::Success().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetCallbackError()

std::pair< XErrorCode, std::string > XrdClHttp::CurlOperation::GetCallbackError ( ) const
inline

Definition at line 236 of file XrdClHttpOps.hh.

236{return std::make_pair(m_callback_error_code, m_callback_error_str);}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ GetConnCalloutFunc()

CreateConnCalloutType XrdClHttp::CurlOperation::GetConnCalloutFunc ( ) const
inline

Definition at line 92 of file XrdClHttpOps.hh.

92{return m_conn_callout;}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ GetCurlErrorMessage()

std::string XrdClHttp::CurlOperation::GetCurlErrorMessage ( ) const
inline

Definition at line 262 of file XrdClHttpOps.hh.

262 {
263 if (m_curl_error_buffer[0] != '\0')
264 return m_curl_error_buffer;
265 return "";
266 }

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ GetCurlHandle()

CURL * XrdClHttp::CurlOperation::GetCurlHandle ( ) const
inline

Definition at line 227 of file XrdClHttpOps.hh.

227{return m_curl.get();}

References m_curl.

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ GetDefaultSlowRateBytesSec()

int XrdClHttp::CurlOperation::GetDefaultSlowRateBytesSec ( )
inlinestatic

Definition at line 288 of file XrdClHttpOps.hh.

289 {
291 }
static constexpr int m_default_minimum_rate

References m_default_minimum_rate.

◆ GetDefaultStallTimeout()

int XrdClHttp::CurlOperation::GetDefaultStallTimeout ( )
inlinestatic

Definition at line 282 of file XrdClHttpOps.hh.

283 {
284 return std::chrono::duration_cast<std::chrono::seconds>(m_default_stall_interval).count();
285 }

◆ GetError()

OpError XrdClHttp::CurlOperation::GetError ( ) const
inline

Definition at line 230 of file XrdClHttpOps.hh.

230{return m_error;}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ GetHeaderExpiry()

std::chrono::steady_clock::time_point XrdClHttp::CurlOperation::GetHeaderExpiry ( ) const
inline

Definition at line 103 of file XrdClHttpOps.hh.

103 {
104 return m_header_expiry.load(std::memory_order_relaxed);
105 }

References m_header_expiry.

Referenced by XrdClHttp::CurlOptionsOp::CurlOptionsOp(), XrdClHttp::CurlStatOp::CurlStatOp(), GetOperationExpiry(), HeaderTimeoutExpired(), Redirect(), and StartConnectionCallout().

Here is the caller graph for this function:

◆ GetOperationExpiry()

std::chrono::steady_clock::time_point XrdClHttp::CurlOperation::GetOperationExpiry ( )
inline

Definition at line 116 of file XrdClHttpOps.hh.

116 {
117 if (m_last_xfer != std::chrono::steady_clock::time_point()) {
118 return m_last_xfer + m_stall_interval;
119 }
120 // Headers have arrived but no payload byte has been accounted for yet.
121 // The header deadline no longer applies (HeaderTimeoutExpired stops
122 // enforcing it at the same point), so anchor the stall clock on the
123 // last header activity instead of reviving a deadline that is moot.
124 if (m_received_header) {
125 return m_header_lastop + m_stall_interval;
126 }
127 return GetHeaderExpiry();
128 }
std::chrono::steady_clock::time_point GetHeaderExpiry() const

References GetHeaderExpiry().

Here is the call graph for this function:

◆ GetResponseInfo()

std::unique_ptr< ResponseInfo > XrdClHttp::CurlOperation::GetResponseInfo ( )

References HeaderTimeoutExpired(), OperationTimeoutExpired(), and TransferStalled().

Here is the call graph for this function:

◆ GetStatusCode()

int XrdClHttp::CurlOperation::GetStatusCode ( ) const
inline

Definition at line 239 of file XrdClHttpOps.hh.

References XrdClHttp::HeaderParser::GetStatusCode(), and m_headers.

Referenced by XrdClHttp::CurlMkcolOp::Fail(), XrdClHttp::CurlTapeOp::Fail(), XrdClHttp::CurlWorker::Run(), XrdClHttp::CurlTapeOp::Success(), and XrdClHttp::CurlVectorReadOp::Write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetStatusMessage()

std::string XrdClHttp::CurlOperation::GetStatusMessage ( ) const
inline

Definition at line 242 of file XrdClHttpOps.hh.

242{return m_headers.GetStatusMessage();}
std::string GetStatusMessage() const

References XrdClHttp::HeaderParser::GetStatusMessage(), and m_headers.

Referenced by XrdClHttp::CurlWorker::Run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTriedBoker()

bool XrdClHttp::CurlOperation::GetTriedBoker ( ) const
inline

Definition at line 177 of file XrdClHttpOps.hh.

177{return m_tried_broker;} // Returns true if the connection broker has been tried.

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ GetUrl()

const std::string & XrdClHttp::CurlOperation::GetUrl ( ) const
inline

Definition at line 187 of file XrdClHttpOps.hh.

187{return m_request_url;}

References m_request_url.

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ GetVerb()

virtual HttpVerb XrdClHttp::CurlOperation::GetVerb ( ) const
pure virtual

Implemented in XrdClHttp::CurlChecksumOp, XrdClHttp::CurlCopyOp, XrdClHttp::CurlDeleteOp, XrdClHttp::CurlListdirOp, XrdClHttp::CurlMkcolOp, XrdClHttp::CurlOptionsOp, XrdClHttp::CurlPgReadOp, XrdClHttp::CurlPutOp, XrdClHttp::CurlReadOp, XrdClHttp::CurlStatOp, XrdClHttp::CurlTapeOp, and XrdClHttp::CurlVectorReadOp.

References GetVerbString().

Referenced by FinishSetup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetVerbString()

const std::string CurlOperation::GetVerbString ( CurlOperation::HttpVerb verb)
static

Definition at line 292 of file XrdClHttpOps.cc.

293{
294 switch (verb) {
295 case HttpVerb::COPY:
296 return "COPY";
297 case HttpVerb::DELETE:
298 return "DELETE";
299 case HttpVerb::GET:
300 return "GET";
301 case HttpVerb::POST:
302 return "POST";
303 case HttpVerb::HEAD:
304 return "HEAD";
305 case HttpVerb::MKCOL:
306 return "MKCOL";
308 return "OPTIONS";
310 return "PROPFIND";
311 case HttpVerb::PUT:
312 return "PUT";
313 case HttpVerb::Count:
314 return "UNKNOWN";
315 }
316 return "UNKNOWN";
317}

References XrdClHttp::COPY, XrdClHttp::Count, XrdClHttp::DELETE, XrdClHttp::GET, XrdClHttp::HEAD, XrdClHttp::MKCOL, XrdClHttp::OPTIONS, XrdClHttp::POST, XrdClHttp::PROPFIND, and XrdClHttp::PUT.

Referenced by FinishSetup(), XrdClHttp::CurlWorker::GetMonitoringJson(), and GetVerb().

Here is the caller graph for this function:

◆ HasFailed()

bool XrdClHttp::CurlOperation::HasFailed ( ) const
inline

Definition at line 251 of file XrdClHttpOps.hh.

251{return m_has_failed.load(std::memory_order_acquire);}

◆ HeaderTimeoutExpired()

bool CurlOperation::HeaderTimeoutExpired ( const std::chrono::steady_clock::time_point & now)

Definition at line 502 of file XrdClHttpOps.cc.

502 {
503 if (m_received_header) return false;
504
505 if (now > GetHeaderExpiry()) {
506 if (m_error == OpError::ErrNone) m_error = OpError::ErrHeaderTimeout;
507 return true;
508 }
509 return false;
510}

References ErrHeaderTimeout, ErrNone, and GetHeaderExpiry().

Referenced by GetResponseInfo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsDone()

bool XrdClHttp::CurlOperation::IsDone ( ) const
inline

Definition at line 245 of file XrdClHttpOps.hh.

245{return m_done;}

Referenced by XrdClHttp::CurlReadOp::ContinueHandle(), and XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ IsPaused()

bool XrdClHttp::CurlOperation::IsPaused ( ) const
inline

Definition at line 248 of file XrdClHttpOps.hh.

248{return m_is_paused;}

Referenced by XrdClHttp::CurlWorker::Run(), StatisticsReset(), and TransferStalled().

Here is the caller graph for this function:

◆ IsRedirect()

bool XrdClHttp::CurlOperation::IsRedirect ( ) const
inline

Definition at line 161 of file XrdClHttpOps.hh.

161{return m_headers.GetStatusCode() >= 300 && m_headers.GetStatusCode() < 400;}

References XrdClHttp::HeaderParser::GetStatusCode(), and m_headers.

Referenced by XrdClHttp::CurlWorker::Run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MoveResponseInfo()

std::unique_ptr< ResponseInfo > XrdClHttp::CurlOperation::MoveResponseInfo ( )
inline

Definition at line 233 of file XrdClHttpOps.hh.

233{return std::move(m_response_info);}

Referenced by XrdClHttp::CurlChecksumOp::Success(), XrdClHttp::CurlDeleteOp::Success(), XrdClHttp::CurlListdirOp::Success(), XrdClHttp::CurlMkcolOp::Success(), and XrdClHttp::CurlStatOp::SuccessImpl().

Here is the caller graph for this function:

◆ OperationTimeoutExpired()

bool CurlOperation::OperationTimeoutExpired ( const std::chrono::steady_clock::time_point & now)

Definition at line 513 of file XrdClHttpOps.cc.

513 {
514 if (m_operation_expiry == std::chrono::steady_clock::time_point{} ||
515 !m_received_header) {
516 return false;
517 }
518
519 if (now > m_operation_expiry) {
520 if (m_error == OpError::ErrNone) m_error = OpError::ErrOperationTimeout;
521 return true;
522 }
523 return false;
524}
std::chrono::steady_clock::time_point m_operation_expiry

References ErrNone, ErrOperationTimeout, and m_operation_expiry.

Referenced by GetResponseInfo().

Here is the caller graph for this function:

◆ OptionsDone()

virtual void XrdClHttp::CurlOperation::OptionsDone ( )
inlinevirtual

Reimplemented in XrdClHttp::CurlChecksumOp, and XrdClHttp::CurlStatOp.

Definition at line 184 of file XrdClHttpOps.hh.

184{}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ Redirect()

CurlOperation::RedirectAction CurlOperation::Redirect ( std::string & target)
virtual

Reimplemented in XrdClHttp::CurlChecksumOp, and XrdClHttp::CurlStatOp.

Definition at line 352 of file XrdClHttpOps.cc.

353{
354 m_callout.reset();
355 m_conn_callout_result = -1;
356 m_conn_callout_listener = -1;
357 m_tried_broker = false;
358
359 auto location = m_headers.GetLocation();
360 if (location.empty()) {
361 m_logger->Warning(kLogXrdClHttp, "After request to %s, server returned a redirect with no new location", m_request_url.c_str());
362 Fail(XrdCl::errErrorResponse, kXR_ServerError, "Server returned redirect without updated location");
364 }
365 if (location.size() && location[0] == '/') { // hostname not included in the location - redirect to self.
366 std::string_view orig_url(m_request_url);
367 auto scheme_loc = orig_url.find("://");
368 if (scheme_loc == std::string_view::npos) {
369 Fail(XrdCl::errErrorResponse, kXR_ServerError, "Server returned a location with unknown hostname");
371 }
372 auto path_loc = orig_url.find('/', scheme_loc + 3);
373 if (path_loc == std::string_view::npos) {
374 location = m_request_url + location;
375 } else {
376 location = std::string(orig_url.substr(0, path_loc)) + location;
377 }
378 }
379 m_logger->Debug(kLogXrdClHttp, "Request for %s redirected to %s", m_request_url.c_str(), location.c_str());
380 m_request_url = DavToHttp(location);
381 target = m_request_url;
382 curl_easy_setopt(m_curl.get(), CURLOPT_URL, m_request_url.c_str());
383 int disable_x509;
384 auto env = XrdCl::DefaultEnv::GetEnv();
385 if (env->GetInt("HttpDisableX509", disable_x509) && !disable_x509) {
386 std::string cert, key;
387 env->GetString("HttpClientCertFile", cert);
388 env->GetString("HttpClientKeyFile", key);
389 if (!cert.empty())
390 curl_easy_setopt(m_curl.get(), CURLOPT_SSLCERT, cert.c_str());
391 if (!key.empty())
392 curl_easy_setopt(m_curl.get(), CURLOPT_SSLKEY, key.c_str());
393 }
395
396 if (m_conn_callout) {
397 auto conn_callout = m_conn_callout(m_request_url, *m_response_info);
398 if (conn_callout != nullptr) {
399
400 auto [host, port] = ParseHostPort(m_request_url);
401 if (host.empty() || port == -1) {
402 Fail(XrdCl::errInternal, 0, "Failed to parse host and port from URL " + m_request_url);
404 }
405 auto fake_addr = GetFakeEndpointForHost(host, port);
406 if (!fake_addr || fake_addr->empty()) {
407 Fail(XrdCl::errInternal, 0, "Failed to generate a fake address for host " + host);
409 }
410 m_resolve_slist.reset(curl_slist_append(m_resolve_slist.release(),
411 (host + ":" + std::to_string(port) + ":" + *fake_addr).c_str()));
412 m_logger->Debug(kLogXrdClHttp, "For connection callout in redirect, mapping %s:%d -> %s", host.c_str(), port, fake_addr->c_str());
413
414 m_callout.reset(conn_callout);
415 std::string err;
417 // BeginCallout takes the expiration by non-const reference; hand it
418 // a copy rather than the atomic's storage.
419 auto expiry = GetHeaderExpiry();
420 if ((m_conn_callout_listener = m_callout->BeginCallout(err, expiry)) == -1) {
421 auto errMsg = "Failed to start a connection callout request: " + err;
422 Fail(XrdCl::errInternal, 0, errMsg.c_str());
424 }
425 curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETFUNCTION, CurlOperation::OpenSocketCallback);
426 curl_easy_setopt(m_curl.get(), CURLOPT_CLOSESOCKETFUNCTION, CurlOperation::CloseSocketCallback);
427 curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETDATA, this);
428 curl_easy_setopt(m_curl.get(), CURLOPT_CLOSESOCKETDATA, fake_addr);
429 curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTFUNCTION, CurlOperation::SockOptCallback);
430 curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTDATA, this);
431 curl_easy_setopt(m_curl.get(), CURLOPT_CONNECT_TO, m_resolve_slist.get());
432 }
433 }
434 m_received_header = false;
435
436 m_last_header_reset = m_last_reset = m_header_start = m_start_op = m_header_lastop = std::chrono::steady_clock::now();
438}
@ kXR_ServerError
const std::string & GetLocation() const
void Warning(uint64_t topic, const char *format,...)
Report a warning.
Definition XrdClLog.cc:248
const uint16_t errErrorResponse
const uint16_t errInternal
Internal error.

References XrdClHttp::HeaderParser::HeaderParser(), XrdCl::Log::Debug(), XrdCl::errErrorResponse, XrdCl::errInternal, Fail(), Fail, XrdCl::DefaultEnv::GetEnv(), GetHeaderExpiry(), XrdClHttp::HeaderParser::GetLocation(), XrdClHttp::kLogXrdClHttp, kXR_ServerError, m_curl, m_headers, m_logger, m_request_url, Reinvoke, SetTriedBoker(), and XrdCl::Log::Warning().

Referenced by XrdClHttp::CurlChecksumOp::Redirect(), XrdClHttp::CurlStatOp::Redirect(), and XrdClHttp::CurlWorker::Run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReleaseHandle()

void CurlOperation::ReleaseHandle ( )
virtual

Reimplemented in XrdClHttp::CurlChecksumOp, XrdClHttp::CurlCopyOp, XrdClHttp::CurlDeleteOp, XrdClHttp::CurlListdirOp, XrdClHttp::CurlMkcolOp, XrdClHttp::CurlOpenOp, XrdClHttp::CurlOptionsOp, XrdClHttp::CurlPutOp, XrdClHttp::CurlReadOp, XrdClHttp::CurlStatOp, XrdClHttp::CurlTapeOp, and XrdClHttp::CurlVectorReadOp.

Definition at line 688 of file XrdClHttpOps.cc.

689{
690 m_conn_callout_listener = -1;
691 m_conn_callout_result = -1;
692 m_tried_broker = false;
693 m_callout.reset();
694
695 if (m_curl == nullptr) return;
696 curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETFUNCTION, nullptr);
697 curl_easy_setopt(m_curl.get(), CURLOPT_CLOSESOCKETFUNCTION, nullptr);
698 curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETDATA, nullptr);
699 curl_easy_setopt(m_curl.get(), CURLOPT_CLOSESOCKETDATA, nullptr);
700 curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTFUNCTION, nullptr);
701 curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTDATA, nullptr);
702 curl_easy_setopt(m_curl.get(), CURLOPT_SSLCERT, nullptr);
703 curl_easy_setopt(m_curl.get(), CURLOPT_SSLKEY, nullptr);
704 curl_easy_setopt(m_curl.get(), CURLOPT_HTTPHEADER, nullptr);
705 curl_easy_setopt(m_curl.get(), CURLOPT_CONNECT_TO, nullptr);
706 m_header_slist.reset();
707 m_curl.release();
708}

References m_curl.

Referenced by CurlOperation(), XrdClHttp::CurlCopyOp::ReleaseHandle(), XrdClHttp::CurlDeleteOp::ReleaseHandle(), XrdClHttp::CurlListdirOp::ReleaseHandle(), XrdClHttp::CurlMkcolOp::ReleaseHandle(), XrdClHttp::CurlOptionsOp::ReleaseHandle(), XrdClHttp::CurlPutOp::ReleaseHandle(), XrdClHttp::CurlReadOp::ReleaseHandle(), XrdClHttp::CurlStatOp::ReleaseHandle(), XrdClHttp::CurlTapeOp::ReleaseHandle(), XrdClHttp::CurlVectorReadOp::ReleaseHandle(), and XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ RequiresOptions()

virtual bool XrdClHttp::CurlOperation::RequiresOptions ( ) const
inlinevirtual

Reimplemented in XrdClHttp::CurlStatOp.

Definition at line 181 of file XrdClHttpOps.hh.

181{return false;}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ SetContinueQueue()

virtual void XrdClHttp::CurlOperation::SetContinueQueue ( std::shared_ptr< XrdClHttp::HandlerQueue > queue)
inlinevirtual

Reimplemented in XrdClHttp::CurlPutOp, and XrdClHttp::CurlReadOp.

Definition at line 143 of file XrdClHttpOps.hh.

143{}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ SetDone()

void XrdClHttp::CurlOperation::SetDone ( bool has_failed)
inlineprotected

◆ SetPaused()

void CurlOperation::SetPaused ( bool paused)
protected

Definition at line 451 of file XrdClHttpOps.cc.

451 {
452 m_is_paused = paused;
453 if (m_is_paused) {
454 m_pause_start = std::chrono::steady_clock::now();
455 } else if (m_pause_start != std::chrono::steady_clock::time_point{}) {
456 m_pause_duration += std::chrono::steady_clock::now() - m_pause_start;
457 m_pause_start = std::chrono::steady_clock::time_point{};
458 }
459}

Referenced by XrdClHttp::CurlPutOp::ContinueHandle(), XrdClHttp::CurlReadOp::ContinueHandle(), XrdClHttp::CurlPutOp::Pause(), and XrdClHttp::CurlReadOp::Pause().

Here is the caller graph for this function:

◆ SetSlowRateBytesSec()

void XrdClHttp::CurlOperation::SetSlowRateBytesSec ( int rate)
inlinestatic

Definition at line 294 of file XrdClHttpOps.hh.

295 {
297 }

References m_minimum_transfer_rate.

◆ SetStallTimeout() [1/2]

void XrdClHttp::CurlOperation::SetStallTimeout ( const std::chrono::steady_clock::duration & stall_interval)
inlinestatic

Definition at line 276 of file XrdClHttpOps.hh.

277 {
278 m_stall_interval = stall_interval;
279 }

◆ SetStallTimeout() [2/2]

void XrdClHttp::CurlOperation::SetStallTimeout ( int stall_interval)
inlinestatic

Definition at line 269 of file XrdClHttpOps.hh.

270 {
271 std::chrono::seconds seconds{stall_interval};
272 m_stall_interval = std::chrono::duration_cast<std::chrono::steady_clock::duration>(seconds);
273 }

Referenced by XrdClHttp::File::SetProperty().

Here is the caller graph for this function:

◆ SetTriedBoker()

void XrdClHttp::CurlOperation::SetTriedBoker ( )
inline

Definition at line 178 of file XrdClHttpOps.hh.

178{m_tried_broker = true;} // Note that the connection broker has been attempted.

Referenced by Redirect(), and XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ Setup()

bool CurlOperation::Setup ( CURL * curl,
CurlWorker & worker )
virtual

Reimplemented in XrdClHttp::CurlChecksumOp, XrdClHttp::CurlCopyOp, XrdClHttp::CurlDeleteOp, XrdClHttp::CurlListdirOp, XrdClHttp::CurlMkcolOp, XrdClHttp::CurlOptionsOp, XrdClHttp::CurlPutOp, XrdClHttp::CurlReadOp, XrdClHttp::CurlStatOp, XrdClHttp::CurlTapeOp, and XrdClHttp::CurlVectorReadOp.

Definition at line 575 of file XrdClHttpOps.cc.

576{
577 if (curl == nullptr) {
578 throw std::runtime_error("Unable to setup curl operation with no handle");
579 }
580 struct timespec now;
581 if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) {
582 throw std::runtime_error("Unable to get current time");
583 }
584
585 m_pause_start = {};
586 m_last_header_reset = m_last_reset = m_start_op = m_header_start = m_header_lastop = std::chrono::steady_clock::now();
587
588 m_curl.reset(curl);
589 m_curl_error_buffer[0] = '\0';
590 curl_easy_setopt(m_curl.get(), CURLOPT_URL, m_request_url.c_str());
591 curl_easy_setopt(m_curl.get(), CURLOPT_ERRORBUFFER, m_curl_error_buffer);
592 curl_easy_setopt(m_curl.get(), CURLOPT_HEADERFUNCTION, CurlStatOp::HeaderCallback);
593 curl_easy_setopt(m_curl.get(), CURLOPT_HEADERDATA, this);
594 curl_easy_setopt(m_curl.get(), CURLOPT_WRITEFUNCTION, NullCallback);
595 curl_easy_setopt(m_curl.get(), CURLOPT_WRITEDATA, nullptr);
596 curl_easy_setopt(m_curl.get(), CURLOPT_XFERINFOFUNCTION, CurlOperation::XferInfoCallback);
597 curl_easy_setopt(m_curl.get(), CURLOPT_XFERINFODATA, this);
598 curl_easy_setopt(m_curl.get(), CURLOPT_NOPROGRESS, 0L);
599 // Note: libcurl is not threadsafe unless this option is set.
600 // Before we set it, we saw deadlocks (and partial deadlocks) in practice.
601 curl_easy_setopt(m_curl.get(), CURLOPT_NOSIGNAL, 1L);
602
603 m_parsed_url = std::make_unique<XrdCl::URL>(m_request_url);
604 auto env = XrdCl::DefaultEnv::GetEnv();
605 int disable_x509;
606 if (env->GetInt("HttpDisableX509", disable_x509) && !disable_x509) {
607 auto [cert, key] = worker.ClientX509CertKeyFile();
608 if (!cert.empty()) {
610 "Using client X.509 credential found at %s", cert.c_str());
611 curl_easy_setopt(m_curl.get(), CURLOPT_SSLCERT, cert.c_str());
612 if (key.empty()) {
614 "X.509 client credential specified but not the client key");
615 } else {
616 curl_easy_setopt(m_curl.get(), CURLOPT_SSLKEY, key.c_str());
617 }
618 }
619 }
620
621 if (m_conn_callout) {
622 ResponseInfo info;
623 auto callout = m_conn_callout(m_request_url, info);
624 if (callout) {
625 m_callout.reset(callout);
626 m_conn_callout_listener = -1;
627 m_conn_callout_result = -1;
628 m_tried_broker = false;
629
630 auto [host, port] = ParseHostPort(m_request_url);
631 if (host.empty() || port == -1) {
632 throw std::runtime_error(
633 "Failed to parse host and port from URL " + m_request_url);
634 }
635 auto fake_addr = GetFakeEndpointForHost(host, port);
636 if (!fake_addr || fake_addr->empty()) {
637 throw std::runtime_error("Failed to generate a fake address for host " + host);
638 }
639 m_resolve_slist.reset(curl_slist_append(m_resolve_slist.release(),
640 (host + ":" + std::to_string(port) + ":" + *fake_addr).c_str()));
641 m_logger->Debug(kLogXrdClHttp, "For connection callout in operation setup, mapping %s:%d -> %s", host.c_str(), port, fake_addr->c_str());
642
643 curl_easy_setopt(m_curl.get(), CURLOPT_CONNECT_TO, m_resolve_slist.get());
644
645 curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETFUNCTION, CurlOperation::OpenSocketCallback);
646 curl_easy_setopt(m_curl.get(), CURLOPT_CLOSESOCKETFUNCTION, CurlOperation::CloseSocketCallback);
647 curl_easy_setopt(m_curl.get(), CURLOPT_OPENSOCKETDATA, this);
648 curl_easy_setopt(m_curl.get(), CURLOPT_CLOSESOCKETDATA, fake_addr);
649 curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTFUNCTION, CurlOperation::SockOptCallback);
650 curl_easy_setopt(m_curl.get(), CURLOPT_SOCKOPTDATA, this);
651 }
652 }
653
654 return true;
655}
std::tuple< std::string, std::string > ClientX509CertKeyFile() const

References XrdClHttp::CurlWorker::ClientX509CertKeyFile(), XrdCl::Log::Debug(), XrdCl::Log::Error(), XrdCl::DefaultEnv::GetEnv(), XrdClHttp::kLogXrdClHttp, m_curl, m_logger, and m_request_url.

Referenced by CurlOperation(), XrdClHttp::CurlWorker::Run(), XrdClHttp::CurlCopyOp::Setup(), XrdClHttp::CurlDeleteOp::Setup(), XrdClHttp::CurlListdirOp::Setup(), XrdClHttp::CurlMkcolOp::Setup(), XrdClHttp::CurlOptionsOp::Setup(), XrdClHttp::CurlPutOp::Setup(), XrdClHttp::CurlReadOp::Setup(), XrdClHttp::CurlStatOp::Setup(), XrdClHttp::CurlTapeOp::Setup(), XrdClHttp::CurlVectorReadOp::Setup(), and SetupNextRequest().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetupNextRequest()

bool CurlOperation::SetupNextRequest ( const std::string & url,
CurlWorker & worker )
protected

Definition at line 658 of file XrdClHttpOps.cc.

659{
660 if (!m_curl) return false;
661
662 curl_easy_reset(m_curl.get());
663 ConfigureHandle(m_curl.get(), false);
664
665 m_request_url = DavToHttp(url);
667 m_headers_list.clear();
668 m_header_slist.reset();
669 m_response_info.reset();
670 m_resolve_slist.reset();
671 m_callout.reset();
672 m_conn_callout_listener = -1;
673 m_conn_callout_result = -1;
674 m_tried_broker = false;
675 m_received_header = false;
676 m_error = OpError::ErrNone;
677 m_callback_error_code = kXR_noErrorYet;
678 m_callback_error_str.clear();
679 m_last_xfer = {};
680 m_last_xfer_count = 0;
681 m_ema_rate = -1.0;
682
683 CURL *curl = m_curl.release();
684 return CurlOperation::Setup(curl, worker);
685}
@ kXR_noErrorYet
void CURL
virtual bool Setup(CURL *curl, CurlWorker &)
void ConfigureHandle(CURL *curl, bool verbose)

References XrdClHttp::HeaderParser::HeaderParser(), XrdClHttp::ConfigureHandle(), ErrNone, kXR_noErrorYet, m_curl, m_headers, m_headers_list, m_request_url, and Setup().

Referenced by XrdClHttp::CurlTapeOp::Success().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StartConnectionCallout()

bool CurlOperation::StartConnectionCallout ( std::string & err)

Definition at line 462 of file XrdClHttpOps.cc.

463{
464 auto expiry = GetHeaderExpiry();
465 if ((m_conn_callout_listener = m_callout->BeginCallout(err, expiry)) == -1) {
466 err = "Failed to start a callout for a socket connection: " + err;
467 Fail(XrdCl::errInternal, 1, err.c_str());
468 return false;
469 }
470 return true;
471}

References XrdCl::errInternal, Fail(), and GetHeaderExpiry().

Referenced by XrdClHttp::CurlWorker::Run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StatisticsReset()

std::tuple< uint64_t, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration > CurlOperation::StatisticsReset ( )

Definition at line 474 of file XrdClHttpOps.cc.

474 {
475 auto now = std::chrono::steady_clock::now();
476 std::chrono::steady_clock::duration pre_header{}, post_header{}, pause_duration{};
477 if (m_received_header) {
478 if (m_last_header_reset < m_header_start) {
479 pre_header = m_header_start - m_last_header_reset;
480 m_last_header_reset = m_header_start;
481 }
482 post_header = now - ((m_last_reset < m_header_start) ? m_header_start : m_last_reset);
483 m_last_reset = now;
484 } else {
485 pre_header = now - m_last_header_reset;
486 m_last_header_reset = now;
487 }
488 if (IsPaused()) {
489 m_pause_duration += now - m_pause_start;
490 m_pause_start = now;
491 }
492 if (m_pause_duration != std::chrono::steady_clock::duration::zero()) {
493 pause_duration = m_pause_duration;
494 m_pause_duration = std::chrono::steady_clock::duration::zero();
495 }
496 auto bytes = m_bytes;
497 m_bytes = 0;
498 return {bytes, pre_header, post_header, pause_duration};
499}

References IsPaused().

Here is the call graph for this function:

◆ Success()

virtual void XrdClHttp::CurlOperation::Success ( )
pure virtual

◆ TransferStalled()

bool CurlOperation::TransferStalled ( uint64_t xfer_bytes,
const std::chrono::steady_clock::time_point & now )

Definition at line 527 of file XrdClHttpOps.cc.

528{
529 // First, check to see how long it's been since any data was sent.
530 if (m_last_xfer == std::chrono::steady_clock::time_point()) {
531 m_last_xfer = m_header_lastop;
532 }
533 auto elapsed = now - m_last_xfer;
534 uint64_t xfer_diff = 0;
535 if (xfer > m_last_xfer_count) {
536 xfer_diff = xfer - m_last_xfer_count;
537 m_last_xfer_count = xfer;
538 m_last_xfer = now;
539 }
540
541 // If progress is made in this callback do not classify as stalled
542 if (elapsed > m_stall_interval && xfer_diff == 0) {
544 return true;
545 }
546
547 // Curl updated us with new timing but the byte count hasn't changed; no need to update the EMA.
548 if (xfer_diff == 0) {
549 return false;
550 }
551
552 // If the transfer is not stalled, then we check to see if the exponentially-weighted
553 // moving average of the transfer rate is below the minimum.
554
555 // If the stall interval since the last header hasn't passed, then we don't check for slow transfers.
556 auto elapsed_since_last_headerop = now - m_header_lastop;
557 if (elapsed_since_last_headerop < m_stall_interval) {
558 return false;
559 } else if (m_ema_rate < 0) {
560 m_ema_rate = xfer / std::chrono::duration<double>(elapsed_since_last_headerop).count();
561 }
562 // Calculate the exponential moving average of the transfer rate.
563 double elapsed_seconds = std::chrono::duration<double>(elapsed).count();
564 auto recent_rate = static_cast<double>(xfer_diff) / elapsed_seconds;
565 auto alpha = 1.0 - exp(-elapsed_seconds / std::chrono::duration<double>(m_stall_interval).count());
566 m_ema_rate = (1.0 - alpha) * m_ema_rate + alpha * recent_rate;
567 if (m_ema_rate < static_cast<double>(m_minimum_rate)) {
568 if (m_error == OpError::ErrNone) m_error = OpError::ErrTransferSlow;
569 return true;
570 }
571 return false;
572}

References ErrNone, ErrTransferClientStall, ErrTransferSlow, ErrTransferStall, IsPaused(), and m_minimum_rate.

Referenced by GetResponseInfo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateBytes()

void XrdClHttp::CurlOperation::UpdateBytes ( uint64_t bytes)
inlineprotected

Definition at line 307 of file XrdClHttpOps.hh.

307{m_bytes += bytes;}

Referenced by XrdClHttp::CurlVectorReadOp::Write().

Here is the caller graph for this function:

◆ UseConnectionCallout()

bool XrdClHttp::CurlOperation::UseConnectionCallout ( )
inline

Definition at line 176 of file XrdClHttpOps.hh.

176{return m_callout.get();} // Returns true if the callout should be tried.

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ WaitSocket()

virtual int XrdClHttp::CurlOperation::WaitSocket ( )
inlinevirtual

Definition at line 164 of file XrdClHttpOps.hh.

164{return m_conn_callout_listener;}

Referenced by XrdClHttp::CurlWorker::Run().

Here is the caller graph for this function:

◆ WaitSocketCallback()

int CurlOperation::WaitSocketCallback ( std::string & err)
virtual

Definition at line 813 of file XrdClHttpOps.cc.

814{
815 m_conn_callout_result = m_callout ? m_callout->FinishCallout(err) : -1;
816 if (m_callout && m_conn_callout_result == -1) {
817 m_logger->Error(kLogXrdClHttp, "Error when getting socket callout: %s", err.c_str());
818 } else if (m_callout) {
819 m_logger->Debug(kLogXrdClHttp, "Got callback socket %d", m_conn_callout_result);
820 }
821 return m_conn_callout_result;
822}

References XrdCl::Log::Debug(), XrdCl::Log::Error(), XrdClHttp::kLogXrdClHttp, and m_logger.

Here is the call graph for this function:

Member Data Documentation

◆ m_curl

◆ m_default_minimum_rate

int XrdClHttp::CurlOperation::m_default_minimum_rate {1024 * 256}
staticconstexprprotected

Definition at line 319 of file XrdClHttpOps.hh.

Referenced by GetDefaultSlowRateBytesSec().

◆ m_handler

◆ m_header_callout

HeaderCallout* XrdClHttp::CurlOperation::m_header_callout
protected

Definition at line 339 of file XrdClHttpOps.hh.

Referenced by CurlOperation(), and FinishSetup().

◆ m_header_expiry

std::atomic<std::chrono::steady_clock::time_point> XrdClHttp::CurlOperation::m_header_expiry
protected

Definition at line 336 of file XrdClHttpOps.hh.

Referenced by CurlOperation(), ExtendDeadline(), and GetHeaderExpiry().

◆ m_headers

◆ m_headers_list

◆ m_logger

◆ m_minimum_rate

int XrdClHttp::CurlOperation::m_minimum_rate {m_minimum_transfer_rate}
protected

◆ m_minimum_transfer_rate

int CurlOperation::m_minimum_transfer_rate {CurlOperation::m_default_minimum_rate}
staticprotected

Definition at line 324 of file XrdClHttpOps.hh.

Referenced by SetSlowRateBytesSec().

◆ m_operation_expiry

std::chrono::steady_clock::time_point XrdClHttp::CurlOperation::m_operation_expiry
protected

Definition at line 330 of file XrdClHttpOps.hh.

Referenced by XrdClHttp::CurlStatOp::CurlStatOp(), and OperationTimeoutExpired().

◆ m_request_url

std::string XrdClHttp::CurlOperation::m_request_url
protected

◆ m_url


The documentation for this class was generated from the following files: