XRootD
Loading...
Searching...
No Matches
XrdClHttp::File Class Referencefinal

#include <XrdClHttpFile.hh>

Inheritance diagram for XrdClHttp::File:
Collaboration diagram for XrdClHttp::File:

Public Member Functions

 File (std::shared_ptr< XrdClHttp::HandlerQueue > queue, XrdCl::Log *log)
virtual ~File () noexcept
virtual XrdCl::XRootDStatus Close (XrdCl::ResponseHandler *handler, time_t timeout) override
virtual XrdCl::XRootDStatus Fcntl (const XrdCl::Buffer &arg, XrdCl::ResponseHandler *handler, time_t timeout) override
XrdCl::OpenFlags::Flags Flags () const
struct timespec GetHeaderTimeout (time_t oper_timeout) const
virtual bool GetProperty (const std::string &name, std::string &value) const override
virtual bool IsOpen () const override
virtual XrdCl::XRootDStatus Open (const std::string &url, XrdCl::OpenFlags::Flags flags, XrdCl::Access::Mode mode, XrdCl::ResponseHandler *handler, time_t timeout) override
virtual XrdCl::XRootDStatus PgRead (uint64_t offset, uint32_t size, void *buffer, XrdCl::ResponseHandler *handler, time_t timeout) override
virtual XrdCl::XRootDStatus Read (uint64_t offset, uint32_t size, void *buffer, XrdCl::ResponseHandler *handler, time_t timeout) override
void SetHeaderTimeout (const struct timespec &ts)
virtual bool SetProperty (const std::string &name, const std::string &value) override
virtual XrdCl::XRootDStatus Stat (bool force, XrdCl::ResponseHandler *handler, time_t timeout) override
virtual XrdCl::XRootDStatus VectorRead (const XrdCl::ChunkList &chunks, void *buffer, XrdCl::ResponseHandler *handler, time_t timeout) override
virtual XrdCl::XRootDStatus Write (uint64_t offset, uint32_t size, const void *buffer, XrdCl::ResponseHandler *handler, time_t timeout) override
virtual XrdCl::XRootDStatus Write (uint64_t offset, XrdCl::Buffer &&buffer, XrdCl::ResponseHandler *handler, time_t timeout) override
Public Member Functions inherited from XrdCl::FilePlugIn
virtual ~FilePlugIn ()
 Destructor.
virtual XRootDStatus Clone (const CloneLocations &locs, ResponseHandler *handler, time_t timeout)
virtual std::unique_ptr< ExportedFileTemplateExportTemplate () const
virtual XRootDStatus Fcntl (QueryCode::Code queryCode, const Buffer &arg, ResponseHandler *handler, time_t timeout)
virtual XRootDStatus OpenUsingTemplate (ExportedFileTemplate *templ, const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, time_t timeout)
virtual XRootDStatus PgWrite (uint64_t offset, uint32_t nbpgs, const void *buffer, std::vector< uint32_t > &cksums, ResponseHandler *handler, time_t timeout)
virtual XRootDStatus PreRead (const TractList &tracts, ResponseHandler *handler, time_t timeout)
virtual XRootDStatus Read (uint64_t offset, uint32_t size, Optional< uint64_t > fdoff, int fd, ResponseHandler *handler, time_t timeout=0)
virtual XRootDStatus Sync (ResponseHandler *handler, time_t timeout)
virtual XRootDStatus Truncate (uint64_t size, ResponseHandler *handler, time_t timeout)
virtual XRootDStatus VectorWrite (const ChunkList &chunks, ResponseHandler *handler, time_t timeout=0)
virtual XRootDStatus Visa (ResponseHandler *handler, time_t timeout)
virtual XRootDStatus Write (uint64_t offset, uint32_t size, Optional< uint64_t > fdoff, int fd, ResponseHandler *handler, time_t timeout=0)
virtual XRootDStatus WriteV (uint64_t offset, const struct iovec *iov, int iovcnt, ResponseHandler *handler, time_t timeout=0)

Static Public Member Functions

static const struct timespec & GetDefaultHeaderTimeout ()
static struct timespec GetFederationMetadataTimeout ()
static struct timespec GetHeaderTimeoutWithDefault (time_t oper_timeout, const struct timespec &header_timeout)
static const struct timespec & GetMinimumHeaderTimeout ()
static std::string GetMonitoringJson ()
static struct timespec ParseHeaderTimeout (const std::string &header_value, XrdCl::Log *logger)
static void SetDefaultHeaderTimeout (struct timespec &ts)
static void SetFederationMetadataTimeout (const struct timespec &ts)
static void SetMinimumHeaderTimeout (struct timespec &ts)

Detailed Description

Definition at line 43 of file XrdClHttpFile.hh.

Constructor & Destructor Documentation

◆ File()

XrdClHttp::File::File ( std::shared_ptr< XrdClHttp::HandlerQueue > queue,
XrdCl::Log * log )
inline

Definition at line 45 of file XrdClHttpFile.hh.

45 :
46 m_queue(queue),
47 m_logger(log),
48 m_default_put_handler(new PutDefaultHandler(*this))
49 {}

Referenced by GetHeaderTimeout(), GetHeaderTimeoutWithDefault(), and ParseHeaderTimeout().

Here is the caller graph for this function:

◆ ~File()

File::~File ( )
virtualnoexcept

Definition at line 202 of file XrdClHttpFile.cc.

202 {
203 auto handler = m_put_handler.load(std::memory_order_acquire);
204 if (handler) {
205 // We must wait for all ongoing writes to complete; the XrdCl::File
206 // destructor will trigger a Close() operation when it is called without
207 // waiting for the Close to finish, then invoke our destructor.
208 // If the Close() is still ongoing, then the handler will receive a
209 // callback after its memory is freed.
210 handler->WaitForCompletion();
211 delete handler;
212 }
213}

References ~File().

Referenced by ~File().

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

Member Function Documentation

◆ Close()

XrdCl::XRootDStatus File::Close ( XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::Close

Reimplemented from XrdCl::FilePlugIn.

Definition at line 410 of file XrdClHttpFile.cc.

412{
413 if (!m_is_opened) {
414 m_logger->Error(kLogXrdClHttp, "Cannot close. URL isn't open");
415 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
416 }
417 m_is_opened = false;
418
419 std::unique_ptr<XrdCl::XRootDStatus> status(new XrdCl::XRootDStatus{});
420 if (m_put_op && !m_put_op->HasFailed()) {
421 auto put_size = m_put_offset.load(std::memory_order_relaxed);
422 if (m_asize >= 0 && put_size == m_asize) {
423 if (put_size == m_asize) {
424 m_logger->Debug(kLogXrdClHttp, "Closing a finished file %s", m_url.c_str());
425 } else {
426 m_logger->Debug(kLogXrdClHttp, "Closing a file %s with partial size (offset %llu, expected %lld)",
427 m_url.c_str(), static_cast<unsigned long long>(put_size), static_cast<long long>(m_asize));
428 status.reset(new XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp,
429 0, "Cannot close file with partial size"));
430 }
431 } else {
432 m_logger->Debug(kLogXrdClHttp, "Flushing final write buffer on close");
433 auto put_handler = m_put_handler.load(std::memory_order_acquire);
434 if (put_handler) {
435 return put_handler->QueueWrite(std::make_pair(nullptr, 0), handler);
436 } else {
437 m_logger->Error(kLogXrdClHttp, "Internal state error - put operation ongoing without handle");
438 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
439 }
440 }
441 } else if (!m_put_op && m_open_flags & XrdCl::OpenFlags::Write) {
442 timespec ts;
443 timespec_get(&ts, TIME_UTC);
444 ts.tv_sec += timeout;
445 m_asize = 0;
446 auto handler_wrapper = new PutResponseHandler(new CloseCreateHandler(handler));
447 m_put_handler.store(handler_wrapper, std::memory_order_release);
448 m_put_op.reset(new XrdClHttp::CurlPutOp(
449 handler_wrapper, m_default_put_handler, m_url, nullptr, 0, ts, m_logger,
450 GetConnCallout(), &m_default_header_callout
451 ));
452 handler_wrapper->SetOp(m_put_op);
453 m_url_current = "";
454 m_last_url = "";
455 m_logger->Debug(kLogXrdClHttp, "Creating a zero-sized object at %s for close", m_url.c_str());
456 try {
457 m_queue->Produce(m_put_op);
458 } catch (...) {
459 m_put_handler.store(nullptr, std::memory_order_release);
460 m_logger->Warning(kLogXrdClHttp, "Failed to add put op to queue");
461 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
462 }
463 return {};
464 }
465
466 m_logger->Debug(kLogXrdClHttp, "Closed %s", m_url.c_str());
467 m_url_current = "";
468 m_last_url = "";
469
470 if (handler) {
471 handler->HandleResponse(status.release(), nullptr);
472 }
473 return XrdCl::XRootDStatus();
474}
static std::string ts()
timestamp output for logging messages
Definition XrdCephOss.cc:53
virtual void HandleResponse(XRootDStatus *status, AnyObject *response)
const uint64_t kLogXrdClHttp
const uint16_t stError
An error occurred that could potentially be retried.
const uint16_t errInvalidOp
const uint16_t errOSError
@ Write
Open only for writing.

References XrdCl::errInvalidOp, XrdCl::errOSError, XrdCl::ResponseHandler::HandleResponse(), XrdClHttp::kLogXrdClHttp, XrdCl::stError, ts(), and XrdCl::OpenFlags::Write.

Here is the call graph for this function:

◆ Fcntl()

XrdCl::XRootDStatus File::Fcntl ( const XrdCl::Buffer & arg,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::Fcntl

Reimplemented from XrdCl::FilePlugIn.

Definition at line 514 of file XrdClHttpFile.cc.

516{
517 if (!m_is_opened) {
518 m_logger->Error(kLogXrdClHttp, "Cannot run fcntl. URL isn't open");
519 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
520 }
521
522 auto obj = new XrdCl::AnyObject();
523 std::string as = arg.ToString();
524 try
525 {
527 if (code == XrdCl::QueryCode::XAttr)
528 {
529 nlohmann::json xatt;
530 std::string etagRes;
531 if (GetProperty("ETag", etagRes))
532 {
533 xatt["ETag"] = etagRes;
534 }
535 std::string cc;
536 if (GetProperty("Cache-Control", cc))
537 {
538 if (cc.find("must-revalidate") != std::string::npos)
539 {
540 xatt["revalidate"] = true;
541 }
542 size_t fm = cc.find("max-age=");
543 if (fm != std::string::npos)
544 {
545 fm += 9; // idx of the first character after the make-age= match
546 for (size_t i = fm; i < cc.length(); i++)
547 {
548 if (!std::isdigit(cc[i]))
549 {
550 std::string sa = cc.substr(fm, i);
551 long int a = std::stol(sa);
552 time_t t = time(NULL) + a;
553 xatt["expire"] = t;
554 break;
555 }
556 }
557 }
558 }
559 XrdCl::Buffer *respBuff = new XrdCl::Buffer();
560 m_logger->Debug(kLogXrdClHttp, "Fcntl content %s", xatt.dump().c_str());
561 respBuff->FromString(xatt.dump());
562 obj->Set(respBuff);
563 }
564 //
565 // Query codes supported by XrdCl::File::Fctnl
566 //
567 else {
568 std::string msg;
569 XrdCl::XRootDStatus status = XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
570 switch (code) {
572 msg = "Server status query not supported.";
573 break;
574 case XrdCl::QueryCode::Checksum: // fallthrough
576 msg = "Checksum query not supported.";
577 break;
579 msg = "Server configuration query not supported.";
580 break;
582 msg = "Local space stats query not supported.";
583 break;
584 case XrdCl::QueryCode::Opaque: // fallthrough
586 // XrdCl implementation dependent
587 msg = "Opaque query not supported.";
588 break;
590 msg = "Prepare status query not supported.";
591 break;
592 default:
593 msg = "Invalid information query type code";
594 }
595 m_logger->Error(kLogXrdClHttp, "%s", msg.c_str());
596 return status;
597 }
598 }
599 catch (const std::exception& e)
600 {
601 m_logger->Warning(kLogXrdClHttp, "Failed to parse query code %s", e.what());
602 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errDataError);
603 }
604
605 handler->HandleResponse(new XrdCl::XRootDStatus(), obj);
606 return XrdCl::XRootDStatus();
607}
virtual bool GetProperty(const std::string &name, std::string &value) const override
void FromString(const std::string str)
Fill the buffer from a string.
std::string ToString() const
Convert the buffer to a string.
const uint16_t errDataError
data is corrupted
Code
XRootD query request codes.
@ OpaqueFile
Implementation dependent.
@ XAttr
Query file extended attributes.
@ Opaque
Implementation dependent.
@ Config
Query server configuration.
@ Stats
Query server stats.
@ ChecksumCancel
Query file checksum cancellation.
@ Checksum
Query file checksum.
@ Space
Query logical space stats.
@ Prepare
Query prepare status.

References XrdCl::QueryCode::Checksum, XrdCl::QueryCode::ChecksumCancel, XrdCl::QueryCode::Config, XrdCl::errDataError, XrdCl::errInvalidOp, XrdCl::Buffer::FromString(), GetProperty(), XrdCl::ResponseHandler::HandleResponse(), XrdClHttp::kLogXrdClHttp, XrdCl::QueryCode::Opaque, XrdCl::QueryCode::OpaqueFile, XrdCl::QueryCode::Prepare, XrdCl::QueryCode::Space, XrdCl::QueryCode::Stats, XrdCl::stError, XrdCl::Buffer::ToString(), and XrdCl::QueryCode::XAttr.

Here is the call graph for this function:

◆ Flags()

XrdCl::OpenFlags::Flags XrdClHttp::File::Flags ( ) const
inline

Definition at line 107 of file XrdClHttpFile.hh.

107{return m_open_flags;}

References Flags().

Referenced by Flags().

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

◆ GetDefaultHeaderTimeout()

const struct timespec & XrdClHttp::File::GetDefaultHeaderTimeout ( )
inlinestatic

Definition at line 119 of file XrdClHttpFile.hh.

119{return m_default_header_timeout;}

Referenced by ParseHeaderTimeout().

Here is the caller graph for this function:

◆ GetFederationMetadataTimeout()

struct timespec XrdClHttp::File::GetFederationMetadataTimeout ( )
inlinestatic

Definition at line 137 of file XrdClHttpFile.hh.

137{return m_fed_timeout;}

References GetFederationMetadataTimeout().

Referenced by GetFederationMetadataTimeout().

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

◆ GetHeaderTimeout()

struct timespec File::GetHeaderTimeout ( time_t oper_timeout) const

Definition at line 282 of file XrdClHttpFile.cc.

283{
284 return GetHeaderTimeoutWithDefault(oper_timeout, m_header_timeout);
285}
static struct timespec GetHeaderTimeoutWithDefault(time_t oper_timeout, const struct timespec &header_timeout)

References File(), GetHeaderTimeout(), and GetHeaderTimeoutWithDefault().

Referenced by GetHeaderTimeout(), Open(), PgRead(), Read(), VectorRead(), Write(), and Write().

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

◆ GetHeaderTimeoutWithDefault()

struct timespec File::GetHeaderTimeoutWithDefault ( time_t oper_timeout,
const struct timespec & header_timeout )
static

Definition at line 262 of file XrdClHttpFile.cc.

263{
264 if (oper_timeout == 0) {
266 XrdCl::DefaultEnv::GetEnv()->GetInt( "RequestTimeout", val );
267 oper_timeout = val;
268 }
269 if (oper_timeout <= 0) {
270 return header_timeout;
271 }
272 if (oper_timeout == header_timeout.tv_sec) {
273 return {header_timeout.tv_sec, 0};
274 } else if (header_timeout.tv_sec < oper_timeout) {
275 return header_timeout;
276 } else { // header timeout is larger than the operation timeout
277 return {oper_timeout, 0};
278 }
279}
static Env * GetEnv()
Get default client environment.
bool GetInt(const std::string &key, int &value)
Definition XrdClEnv.cc:89
const int DefaultRequestTimeout

References File(), XrdCl::DefaultRequestTimeout, XrdCl::DefaultEnv::GetEnv(), GetHeaderTimeoutWithDefault(), and XrdCl::Env::GetInt().

Referenced by GetHeaderTimeout(), and GetHeaderTimeoutWithDefault().

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

◆ GetMinimumHeaderTimeout()

const struct timespec & XrdClHttp::File::GetMinimumHeaderTimeout ( )
inlinestatic

Definition at line 113 of file XrdClHttpFile.hh.

113{return m_min_client_timeout;}

Referenced by ParseHeaderTimeout().

Here is the caller graph for this function:

◆ GetMonitoringJson()

std::string File::GetMonitoringJson ( )
static

Definition at line 288 of file XrdClHttpFile.cc.

289{
290 return "{\"prefetch\": {"
291 "\"count\": " + std::to_string(m_prefetch_count) + ","
292 "\"expired\": " + std::to_string(m_prefetch_expired_count) + ","
293 "\"failed\": " + std::to_string(m_prefetch_failed_count) + ","
294 "\"reads_hit\": " + std::to_string(m_prefetch_reads_hit) + ","
295 "\"reads_miss\": " + std::to_string(m_prefetch_reads_miss) + ","
296 "\"bytes_used\": " + std::to_string(m_prefetch_bytes_used) +
297 "}}";
298}

◆ GetProperty()

bool File::GetProperty ( const std::string & name,
std::string & value ) const
overridevirtual
See also
XrdCl::File::GetProperty

Reimplemented from XrdCl::FilePlugIn.

Definition at line 985 of file XrdClHttpFile.cc.

987{
988 if (name == "CurrentURL") {
989 value = GetCurrentURL();
990 return true;
991 }
992
993 if (name == "IsPrefetching") {
994 value = m_default_prefetch_handler->IsPrefetching() ? "true" : "false";
995 return true;
996 }
997
998 std::shared_lock lock(m_properties_mutex);
999 if (name == "LastURL") {
1000 value = m_last_url;
1001 return true;
1002 }
1003
1004 const auto p = m_properties.find(name);
1005 if (p == std::end(m_properties)) {
1006 return false;
1007 }
1008
1009 value = p->second;
1010 return true;
1011}

Referenced by Fcntl(), and Stat().

Here is the caller graph for this function:

◆ IsOpen()

bool File::IsOpen ( ) const
overridevirtual
See also
XrdCl::File::IsOpen

Reimplemented from XrdCl::FilePlugIn.

Definition at line 979 of file XrdClHttpFile.cc.

980{
981 return m_is_opened;
982}

◆ Open()

XrdCl::XRootDStatus File::Open ( const std::string & url,
XrdCl::OpenFlags::Flags flags,
XrdCl::Access::Mode mode,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::Open

Reimplemented from XrdCl::FilePlugIn.

Definition at line 301 of file XrdClHttpFile.cc.

306{
307 if (m_is_opened) {
308 m_logger->Error(kLogXrdClHttp, "URL %s already open", url.c_str());
309 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
310 }
311
312 // Note: workaround for a design flaw of the XrdCl API.
313 //
314 // Any properties we set on the file *prior* to opening it are sent to the
315 // XrdCl base implementation, not the plugin object. Hence, they are effectively
316 // ignored because the later `GetProperty` accesses a different object. We want
317 // the SetProperty calls to take effect because they are needed for successfully
318 // `Open`ing the file. There's no way to "setup the plugin", "set properties", and
319 // then "open file" because the first and third operations are part of the same API
320 // call. We thus allow the caller to trigger the plugin loading by doing a special
321 // `Open` call (flags set to Compress, access mode None) that is a no-op.
322 //
323 // Contrast the XrdCl::File plugin loading style with XrdCl::Filesystem; the latter
324 // gets a target URL on construction, before any operations are done, allowing
325 // the `SetProperty` to work.
326 if ((flags == XrdCl::OpenFlags::Compress) && (mode == XrdCl::Access::None) &&
327 (handler == nullptr) && (timeout == 0))
328 {
329 return XrdCl::XRootDStatus();
330 }
331
332 m_open_flags = flags;
333
334 m_header_timeout.tv_nsec = m_default_header_timeout.tv_nsec;
335 m_header_timeout.tv_sec = m_default_header_timeout.tv_sec;
336 auto parsed_url = XrdCl::URL();
337 parsed_url.SetPort(0);
338 if (!parsed_url.FromString(url)) {
339 m_logger->Error(kLogXrdClHttp, "Failed to parse provided URL as a valid URL: %s", url.c_str());
340 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidArgs);
341 }
342 auto pm = parsed_url.GetParams();
343 auto iter = pm.find("xrdclhttp.timeout");
344 std::string timeout_string = (iter == pm.end()) ? "" : iter->second;
345 m_header_timeout = ParseHeaderTimeout(timeout_string, m_logger);
346 pm["xrdclhttp.timeout"] = XrdClHttp::MarshalDuration(m_header_timeout);
347 parsed_url.SetParams(pm);
348 iter = pm.find("oss.asize");
349 if (iter != pm.end()) {
350 off_t asize;
351 auto ec = std::from_chars(iter->second.c_str(), iter->second.c_str() + iter->second.size(), asize);
352 if ((ec.ec == std::errc()) && (ec.ptr == iter->second.c_str() + iter->second.size()) && asize >= 0) {
353 m_asize = asize;
354 } else {
355 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp, 0, "Unable to parse oss.asize to a valid size");
356 }
357 pm.erase(iter);
358 parsed_url.SetParams(pm);
359 }
360
361 m_url = parsed_url.GetURL();
362 m_last_url = "";
363 m_url_current = "";
364
365 auto ts = GetHeaderTimeout(timeout);
366
367 bool full_download = m_full_download.load(std::memory_order_relaxed);
368 m_default_prefetch_handler.reset(new PrefetchDefaultHandler(*this));
369 if (full_download) {
370 m_default_prefetch_handler->m_prefetch_enabled.store(true, std::memory_order_relaxed);
371 }
372
373 if (full_download && !(flags & XrdCl::OpenFlags::Write)) {
374 m_logger->Debug(kLogXrdClHttp, "Opening %s in full download mode", m_url.c_str());
375
376 handler = new OpenFullDownloadResponseHandler(&m_is_opened, SendResponseInfo(), handler);
377 m_prefetch_size = std::numeric_limits<off_t>::max();
378 auto [status, ok] = ReadPrefetch(0, 0, nullptr, handler, timeout, false);
379 if (ok) {
380 return status;
381 } else {
382 m_logger->Error(kLogXrdClHttp, "Failed to start prefetch of data at open (URL %s): %s", m_url.c_str(), status.ToString().c_str());
383 return status;
384 }
385 }
386
387
388 m_logger->Debug(kLogXrdClHttp, "Opening %s (with timeout %lld)", m_url.c_str(), (long long) timeout);
389
390 // This response handler sets the m_is_opened flag to true if the open callback is successfully invoked.
391 handler = new OpenResponseHandler(&m_is_opened, handler);
392
393 std::shared_ptr<XrdClHttp::CurlOpenOp> openOp(
394 new XrdClHttp::CurlOpenOp(
395 handler, GetCurrentURL(), ts, m_logger, this, SendResponseInfo(), GetConnCallout(),
396 &m_default_header_callout
397 )
398 );
399 try {
400 m_queue->Produce(std::move(openOp));
401 } catch (...) {
402 m_logger->Warning(kLogXrdClHttp, "Failed to add open op to queue");
403 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
404 }
405
406 return XrdCl::XRootDStatus();
407}
static struct timespec ParseHeaderTimeout(const std::string &header_value, XrdCl::Log *logger)
struct timespec GetHeaderTimeout(time_t oper_timeout) const
std::string MarshalDuration(const struct timespec &timeout)
const uint16_t errInvalidArgs

References XrdCl::OpenFlags::Compress, ec, XrdCl::errInvalidArgs, XrdCl::errInvalidOp, XrdCl::errOSError, GetHeaderTimeout(), XrdClHttp::kLogXrdClHttp, XrdClHttp::MarshalDuration(), XrdCl::Access::None, ParseHeaderTimeout(), XrdCl::stError, XrdCl::Status::ToString(), ts(), and XrdCl::OpenFlags::Write.

Here is the call graph for this function:

◆ ParseHeaderTimeout()

struct timespec File::ParseHeaderTimeout ( const std::string & header_value,
XrdCl::Log * logger )
static

Definition at line 234 of file XrdClHttpFile.cc.

235{
236 struct timespec ts = File::GetDefaultHeaderTimeout();
237 if (!timeout_string.empty()) {
238 std::string errmsg;
239 // Parse the provided timeout and decrease by a second if we can (if it's below a second, halve it).
240 // The thinking is that if the client needs a response in N seconds, then we ought to set the internal
241 // timeout to (N-1) seconds to provide enough time for our response to arrive at the client.
242 if (!XrdClHttp::ParseTimeout(timeout_string, ts, errmsg)) {
243 logger->Error(kLogXrdClHttp, "Failed to parse xrdclhttp.timeout parameter: %s", errmsg.c_str());
244 } else if (ts.tv_sec >= 1) {
245 ts.tv_sec--;
246 } else {
247 ts.tv_nsec /= 2;
248 }
249 }
250 const auto mct = File::GetMinimumHeaderTimeout();
251 if (ts.tv_sec < mct.tv_sec ||
252 (ts.tv_sec == mct.tv_sec && ts.tv_nsec < mct.tv_nsec))
253 {
254 ts.tv_sec = mct.tv_sec;
255 ts.tv_nsec = mct.tv_nsec;
256 }
257
258 return ts;
259}
static const struct timespec & GetDefaultHeaderTimeout()
static const struct timespec & GetMinimumHeaderTimeout()
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition XrdClLog.cc:231
bool ParseTimeout(const std::string &duration, struct timespec &, std::string &errmsg)

References File(), GetDefaultHeaderTimeout(), GetMinimumHeaderTimeout(), XrdClHttp::kLogXrdClHttp, ParseHeaderTimeout(), XrdClHttp::ParseTimeout(), and ts().

Referenced by Open(), and ParseHeaderTimeout().

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

◆ PgRead()

XrdCl::XRootDStatus File::PgRead ( uint64_t offset,
uint32_t size,
void * buffer,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl:File PgRead

Reimplemented from XrdCl::FilePlugIn.

Definition at line 934 of file XrdClHttpFile.cc.

939{
940 if (!m_is_opened) {
941 m_logger->Error(kLogXrdClHttp, "Cannot pgread. URL isn't open");
942 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
943 }
944 auto [status, ok] = ReadPrefetch(offset, size, buffer, handler, timeout, true);
945 if (ok) {
946 if (status.IsOK()) {
947 m_logger->Debug(kLogXrdClHttp, "PgRead %s (%d bytes at offset %lld) will be served from prefetch handler", m_url.c_str(), size, static_cast<long long>(offset));
948 } else {
949 m_logger->Warning(kLogXrdClHttp, "PgRead %s (%d bytes at offset %lld) failed: %s", m_url.c_str(), size, static_cast<long long>(offset), status.GetErrorMessage().c_str());
950 }
951 return status;
952 } else if (m_full_download.load(std::memory_order_relaxed)) {
953 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp, 0, "Non-sequential read detected when in full-download mode");
954 }
955
956 auto ts = GetHeaderTimeout(timeout);
957 auto url = GetCurrentURL();
958 m_logger->Debug(kLogXrdClHttp, "PgRead %s (%d bytes at offset %lld)", url.c_str(), size, static_cast<long long>(offset));
959
960 std::shared_ptr<XrdClHttp::CurlPgReadOp> readOp(
961 new XrdClHttp::CurlPgReadOp(
962 handler, m_default_prefetch_handler, url, ts, std::make_pair(offset, size),
963 static_cast<char*>(buffer), size, m_logger,
964 GetConnCallout(), &m_default_header_callout
965 )
966 );
967
968 try {
969 m_queue->Produce(std::move(readOp));
970 } catch (...) {
971 m_logger->Warning(kLogXrdClHttp, "Failed to add read op to queue");
972 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
973 }
974
975 return XrdCl::XRootDStatus();
976}

References XrdCl::errInvalidOp, XrdCl::errOSError, XrdCl::XRootDStatus::GetErrorMessage(), GetHeaderTimeout(), XrdCl::Status::IsOK(), XrdClHttp::kLogXrdClHttp, XrdCl::stError, and ts().

Here is the call graph for this function:

◆ Read()

XrdCl::XRootDStatus File::Read ( uint64_t offset,
uint32_t size,
void * buffer,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::Read

Reimplemented from XrdCl::FilePlugIn.

Definition at line 610 of file XrdClHttpFile.cc.

615{
616 if (!m_is_opened) {
617 m_logger->Error(kLogXrdClHttp, "Cannot read. URL isn't open");
618 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
619 }
620 auto [status, ok] = ReadPrefetch(offset, size, buffer, handler, timeout, false);
621 if (ok) {
622 if (status.IsOK()) {
623 m_logger->Debug(kLogXrdClHttp, "Read %s (%d bytes at offset %lld) will be served from prefetch handler", m_url.c_str(), size, static_cast<long long>(offset));
624 } else {
625 m_logger->Warning(kLogXrdClHttp, "Read %s (%d bytes at offset %lld) failed: %s", m_url.c_str(), size, static_cast<long long>(offset), status.GetErrorMessage().c_str());
626 }
627 return status;
628 } else if (m_full_download.load(std::memory_order_relaxed)) {
629 std::unique_lock lock(m_default_prefetch_handler->m_prefetch_mutex);
630 if (m_prefetch_op && m_prefetch_op->IsDone() && (static_cast<off_t>(offset) == m_prefetch_offset.load(std::memory_order_acquire))) {
631 if (handler) {
632 auto ci = new XrdCl::ChunkInfo(offset, 0, buffer);
633 auto obj = new XrdCl::AnyObject();
634 obj->Set(ci);
635 handler->HandleResponse(new XrdCl::XRootDStatus{}, obj);
636 }
637 return XrdCl::XRootDStatus{};
638 }
639 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp, 0, "Non-sequential read detected when in full-download mode");
640 }
641
642 auto ts = GetHeaderTimeout(timeout);
643 auto url = GetCurrentURL();
644 m_logger->Debug(kLogXrdClHttp, "Read %s (%d bytes at offset %lld with timeout %lld)", url.c_str(), size, static_cast<long long>(offset), static_cast<long long>(ts.tv_sec));
645
646 std::shared_ptr<XrdClHttp::CurlReadOp> readOp(
647 new XrdClHttp::CurlReadOp(
648 handler, m_default_prefetch_handler, url, ts, std::make_pair(offset, size),
649 static_cast<char*>(buffer), size, m_logger,
650 GetConnCallout(), &m_default_header_callout
651 )
652 );
653 try {
654 m_queue->Produce(std::move(readOp));
655 } catch (...) {
656 m_logger->Warning(kLogXrdClHttp, "Failed to add read op to queue");
657 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
658 }
659
660 return XrdCl::XRootDStatus();
661}

References XrdCl::errInvalidOp, XrdCl::errOSError, XrdCl::XRootDStatus::GetErrorMessage(), GetHeaderTimeout(), XrdCl::ResponseHandler::HandleResponse(), XrdCl::Status::IsOK(), XrdClHttp::kLogXrdClHttp, XrdCl::stError, and ts().

Here is the call graph for this function:

◆ SetDefaultHeaderTimeout()

void XrdClHttp::File::SetDefaultHeaderTimeout ( struct timespec & ts)
inlinestatic

Definition at line 116 of file XrdClHttpFile.hh.

116{m_default_header_timeout.tv_sec = ts.tv_sec; m_default_header_timeout.tv_nsec = ts.tv_nsec;}

References ts().

Here is the call graph for this function:

◆ SetFederationMetadataTimeout()

void XrdClHttp::File::SetFederationMetadataTimeout ( const struct timespec & ts)
inlinestatic

Definition at line 134 of file XrdClHttpFile.hh.

134{m_fed_timeout.tv_sec = ts.tv_sec; m_fed_timeout.tv_nsec = ts.tv_nsec;}

References SetFederationMetadataTimeout(), and ts().

Referenced by SetFederationMetadataTimeout().

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

◆ SetHeaderTimeout()

void XrdClHttp::File::SetHeaderTimeout ( const struct timespec & ts)
inline

Definition at line 122 of file XrdClHttpFile.hh.

122{m_header_timeout.tv_sec = ts.tv_sec; m_header_timeout.tv_nsec = ts.tv_nsec;}

References ts().

Here is the call graph for this function:

◆ SetMinimumHeaderTimeout()

void XrdClHttp::File::SetMinimumHeaderTimeout ( struct timespec & ts)
inlinestatic

Definition at line 110 of file XrdClHttpFile.hh.

110{m_min_client_timeout.tv_sec = ts.tv_sec; m_min_client_timeout.tv_nsec = ts.tv_nsec;}

References ts().

Here is the call graph for this function:

◆ SetProperty()

bool File::SetProperty ( const std::string & name,
const std::string & value )
overridevirtual
See also
XrdCl::File::SetProperty

Reimplemented from XrdCl::FilePlugIn.

Definition at line 1019 of file XrdClHttpFile.cc.

1021{
1022 if (name == "XrdClHttpHeaderCallout") {
1023 long long pointer;
1024 try {
1025 pointer = std::stoll(value, nullptr, 16);
1026 } catch (...) {
1027 pointer = 0;
1028 }
1029 m_header_callout.store(reinterpret_cast<XrdClHttp::HeaderCallout*>(pointer), std::memory_order_release);
1030 } else if (name == "XrdClHttpFullDownload") {
1031 if (value == "true") {
1032 auto prefetch_handler = m_default_prefetch_handler;
1033 if (prefetch_handler) {
1034 std::unique_lock lock(prefetch_handler->m_prefetch_mutex);
1035 prefetch_handler->m_prefetch_enabled.store(true, std::memory_order_relaxed);
1036 }
1037 m_full_download.store(true, std::memory_order_relaxed);
1038 }
1039 }
1040
1041 std::unique_lock lock(m_properties_mutex);
1042
1043 m_properties[name] = value;
1044 if (name == "LastURL") {
1045 m_last_url = value;
1046 m_url_current = "";
1047 }
1048 else if (name == "XrdClHttpQueryParam") {
1049 CalculateCurrentURL(value);
1050 }
1051 else if (name == "XrdClHttpMaintenancePeriod") {
1052 unsigned period;
1053 auto ec = std::from_chars(value.c_str(), value.c_str() + value.size(), period);
1054 if ((ec.ec == std::errc()) && (ec.ptr == value.c_str() + value.size()) && period > 0) {
1055 m_logger->Debug(kLogXrdClHttp, "Setting maintenance period to %u", period);
1057 }
1058 }
1059 else if (name == "XrdClHttpStallTimeout") {
1060 std::string errmsg;
1061 timespec ts;
1062 if (!ParseTimeout(value, ts, errmsg)) {
1063 m_logger->Debug(kLogXrdClHttp, "Failed to parse timeout value (%s): %s", value.c_str(), errmsg.c_str());
1064 } else {
1065 CurlOperation::SetStallTimeout(std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec});
1066 }
1067 }
1068 else if (name == "XrdClHttpPrefetchSize") {
1069 off_t size;
1070 auto ec = std::from_chars(value.c_str(), value.c_str() + value.size(), size);
1071 if ((ec.ec == std::errc()) && (ec.ptr == value.c_str() + value.size())) {
1072 lock.unlock();
1073 std::unique_lock lock2(m_default_prefetch_handler->m_prefetch_mutex);
1074 m_prefetch_size = size;
1075 } else {
1076 m_logger->Debug(kLogXrdClHttp, "XrdClHttpPrefetchSize value (%s) was not parseable", value.c_str());
1077 }
1078 }
1079 return true;
1080}
static void SetStallTimeout(int stall_interval)
static void SetMaintenancePeriod(unsigned maint)

References ec, XrdClHttp::kLogXrdClHttp, XrdClHttp::ParseTimeout(), XrdClHttp::CurlWorker::SetMaintenancePeriod(), XrdClHttp::CurlOperation::SetStallTimeout(), and ts().

Here is the call graph for this function:

◆ Stat()

XrdCl::XRootDStatus File::Stat ( bool force,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::Stat

Reimplemented from XrdCl::FilePlugIn.

Definition at line 477 of file XrdClHttpFile.cc.

480{
481 if (!m_is_opened) {
482 m_logger->Error(kLogXrdClHttp, "Cannot stat. URL isn't open");
483 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
484 }
485
486 std::string content_length_str;
487 int64_t content_length;
488 if (!GetProperty("ContentLength", content_length_str)) {
489 m_logger->Error(kLogXrdClHttp, "Content length missing for %s", m_url.c_str());
490 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
491 }
492 try {
493 content_length = std::stoll(content_length_str);
494 } catch (...) {
495 m_logger->Error(kLogXrdClHttp, "Content length not an integer for %s", m_url.c_str());
496 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
497 }
498 if (content_length < 0) {
499 m_logger->Error(kLogXrdClHttp, "Content length negative for %s", m_url.c_str());
500 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidResponse);
501 }
502
503 m_logger->Debug(kLogXrdClHttp, "Successful stat operation on %s (size %lld)", m_url.c_str(), static_cast<long long>(content_length));
504 auto stat_info = new XrdCl::StatInfo("nobody", content_length,
506 auto obj = new XrdCl::AnyObject();
507 obj->Set(stat_info);
508
509 handler->HandleResponse(new XrdCl::XRootDStatus(), obj);
510 return XrdCl::XRootDStatus();
511}
@ IsReadable
Read access is allowed.
const uint16_t errInvalidResponse

References XrdCl::errInvalidOp, XrdCl::errInvalidResponse, GetProperty(), XrdCl::ResponseHandler::HandleResponse(), XrdCl::StatInfo::IsReadable, XrdClHttp::kLogXrdClHttp, and XrdCl::stError.

Here is the call graph for this function:

◆ VectorRead()

XrdCl::XRootDStatus File::VectorRead ( const XrdCl::ChunkList & chunks,
void * buffer,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::VectorRead

Reimplemented from XrdCl::FilePlugIn.

Definition at line 773 of file XrdClHttpFile.cc.

777{
778 if (!m_is_opened) {
779 m_logger->Error(kLogXrdClHttp, "Cannot do vector read: URL isn't open");
780 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
781 } else if (m_full_download.load(std::memory_order_relaxed)) {
782 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp, 0, "Only sequential reads are supported when in full-download mode");
783 }
784 if (chunks.empty()) {
785 if (handler) {
786 auto status = new XrdCl::XRootDStatus();
787 auto vr = std::make_unique<XrdCl::VectorReadInfo>();
788 vr->SetSize(0);
789 auto obj = new XrdCl::AnyObject();
790 obj->Set(vr.release());
791 handler->HandleResponse(status, obj);
792 }
793 return XrdCl::XRootDStatus();
794 }
795
796 auto ts = GetHeaderTimeout(timeout);
797 auto url = GetCurrentURL();
798 m_logger->Debug(kLogXrdClHttp, "Read %s (%lld chunks; first chunk is %u bytes at offset %lld with timeout %lld)", url.c_str(), static_cast<long long>(chunks.size()), static_cast<unsigned>(chunks[0].GetLength()), static_cast<long long>(chunks[0].GetOffset()), static_cast<long long>(ts.tv_sec));
799
800 std::shared_ptr<XrdClHttp::CurlVectorReadOp> readOp(
801 new XrdClHttp::CurlVectorReadOp(
802 handler, url, ts, chunks, m_logger, GetConnCallout(), &m_default_header_callout
803 )
804 );
805 try {
806 m_queue->Produce(std::move(readOp));
807 } catch (...) {
808 m_logger->Warning(kLogXrdClHttp, "Failed to add vector read op to queue");
809 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
810 }
811
812 return XrdCl::XRootDStatus();
813}

References XrdCl::errInvalidOp, XrdCl::errOSError, GetHeaderTimeout(), XrdCl::ResponseHandler::HandleResponse(), XrdClHttp::kLogXrdClHttp, XrdCl::stError, and ts().

Here is the call graph for this function:

◆ Write() [1/2]

XrdCl::XRootDStatus File::Write ( uint64_t offset,
uint32_t size,
const void * buffer,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::Write

Reimplemented from XrdCl::FilePlugIn.

Definition at line 816 of file XrdClHttpFile.cc.

821{
822 if (!m_is_opened) {
823 m_logger->Error(kLogXrdClHttp, "Cannot write: URL isn't open");
824 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
825 } else if (m_full_download.load(std::memory_order_relaxed)) {
826 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp, 0, "Only sequential reads are supported when in full-download mode");
827 }
828 m_default_prefetch_handler->DisablePrefetch();
829
830 auto ts = GetHeaderTimeout(timeout);
831 auto url = GetCurrentURL();
832 m_logger->Debug(kLogXrdClHttp, "Write %s (%d bytes at offset %lld with timeout %lld)", url.c_str(), size, static_cast<long long>(offset), static_cast<long long>(ts.tv_sec));
833
834 auto handler_wrapper = m_put_handler.load(std::memory_order_relaxed);
835 if (!handler_wrapper) {
836 handler_wrapper = new PutResponseHandler(handler);
837 PutResponseHandler *expected_value = nullptr;
838 if (!m_put_handler.compare_exchange_strong(expected_value, handler_wrapper, std::memory_order_acq_rel)) {
839 delete handler_wrapper;
840 return expected_value->QueueWrite(std::make_pair(buffer, size), handler);
841 }
842
843 if (offset != 0) {
844 m_put_handler.store(nullptr, std::memory_order_release);
845 delete handler_wrapper;
846 m_logger->Warning(kLogXrdClHttp, "Cannot start PUT operation at non-zero offset");
847 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidArgs, 0, "HTTP uploads must start at offset 0");
848 }
849 m_put_op.reset(new XrdClHttp::CurlPutOp(
850 handler_wrapper, m_default_put_handler, url, static_cast<const char*>(buffer), size, ts, m_logger,
851 GetConnCallout(), &m_default_header_callout
852 ));
853 handler_wrapper->SetOp(m_put_op);
854 m_put_offset.fetch_add(size, std::memory_order_acq_rel);
855 try {
856 m_queue->Produce(m_put_op);
857 } catch (...) {
858 m_put_handler.store(nullptr, std::memory_order_release);
859 delete handler_wrapper;
860 m_logger->Warning(kLogXrdClHttp, "Failed to add put op to queue");
861 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
862 }
863 return XrdCl::XRootDStatus();
864 }
865
866 auto old_offset = m_put_offset.fetch_add(size, std::memory_order_acq_rel);
867 if (static_cast<off_t>(offset) != old_offset) {
868 m_put_offset.fetch_sub(size, std::memory_order_acq_rel);
869 m_logger->Warning(kLogXrdClHttp, "Requested write offset at %lld does not match current file descriptor offset at %lld",
870 static_cast<long long>(offset), static_cast<long long>(old_offset));
871 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidArgs, 0, "Requested write offset does not match current offset");
872 }
873 return handler_wrapper->QueueWrite(std::make_pair(buffer, size), handler);
874}

References XrdCl::errInvalidArgs, XrdCl::errInvalidOp, XrdCl::errOSError, GetHeaderTimeout(), XrdClHttp::kLogXrdClHttp, XrdCl::stError, and ts().

Here is the call graph for this function:

◆ Write() [2/2]

XrdCl::XRootDStatus File::Write ( uint64_t offset,
XrdCl::Buffer && buffer,
XrdCl::ResponseHandler * handler,
time_t timeout )
overridevirtual
See also
XrdCl::File::Write

Reimplemented from XrdCl::FilePlugIn.

Definition at line 877 of file XrdClHttpFile.cc.

881{
882 if (!m_is_opened) {
883 m_logger->Error(kLogXrdClHttp, "Cannot write: URL isn't open");
884 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidOp);
885 }
886 m_default_prefetch_handler->DisablePrefetch();
887
888 auto ts = GetHeaderTimeout(timeout);
889 auto url = GetCurrentURL();
890 m_logger->Debug(kLogXrdClHttp, "Write %s (%d bytes at offset %lld with timeout %lld)", url.c_str(), static_cast<int>(buffer.GetSize()), static_cast<long long>(offset), static_cast<long long>(ts.tv_sec));
891
892 auto handler_wrapper = m_put_handler.load(std::memory_order_relaxed);
893 if (!handler_wrapper) {
894 handler_wrapper = new PutResponseHandler(handler);
895 PutResponseHandler *expected_value = nullptr;
896 if (!m_put_handler.compare_exchange_strong(expected_value, handler_wrapper, std::memory_order_acq_rel)) {
897 delete handler_wrapper;
898 return expected_value->QueueWrite(std::move(buffer), handler);
899 }
900
901 if (offset != 0) {
902 m_put_handler.store(nullptr, std::memory_order_release);
903 delete handler_wrapper;
904 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidArgs, 0, "HTTP uploads must start at offset 0");
905 }
906 m_put_op.reset(new XrdClHttp::CurlPutOp(
907 handler_wrapper, m_default_put_handler, url, std::move(buffer), ts, m_logger,
908 GetConnCallout(), &m_default_header_callout
909 ));
910 handler_wrapper->SetOp(m_put_op);
911 m_put_offset.fetch_add(buffer.GetSize(), std::memory_order_acq_rel);
912 try {
913 m_queue->Produce(m_put_op);
914 } catch (...) {
915 m_put_handler.store(nullptr, std::memory_order_release);
916 delete handler_wrapper;
917 m_logger->Warning(kLogXrdClHttp, "Failed to add put op to queue");
918 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errOSError);
919 }
920 return XrdCl::XRootDStatus();
921 }
922
923 auto old_offset = m_put_offset.fetch_add(buffer.GetSize(), std::memory_order_acq_rel);
924 if (static_cast<off_t>(offset) != old_offset) {
925 m_put_offset.fetch_sub(buffer.GetSize(), std::memory_order_acq_rel);
926 m_logger->Warning(kLogXrdClHttp, "Requested write offset at %lld does not match current file descriptor offset at %lld",
927 static_cast<long long>(offset), static_cast<long long>(old_offset));
928 return XrdCl::XRootDStatus(XrdCl::stError, XrdCl::errInvalidArgs, 0, "Requested write offset does not match current offset");
929 }
930 return handler_wrapper->QueueWrite(std::move(buffer), handler);
931}
uint32_t GetSize() const
Get the size of the message.

References XrdCl::errInvalidArgs, XrdCl::errInvalidOp, XrdCl::errOSError, GetHeaderTimeout(), XrdClHttp::kLogXrdClHttp, XrdCl::stError, and ts().

Here is the call graph for this function:

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