XRootD
Loading...
Searching...
No Matches
XrdClHttpParseTimeout.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
22
23#include <stdexcept>
24#include <cstring>
25
26bool XrdClHttp::ParseTimeout(const std::string &duration, struct timespec &result, std::string &errmsg) {
27
28 if (duration.empty()) {
29 errmsg = "cannot parse empty string as a time duration";
30 return false;
31 }
32 if (duration == "0") {
33 result = {0, 0};
34 return true;
35 }
36 struct timespec ts = {0, 0};
37 auto strValue = duration;
38 while (!strValue.empty()) {
39 std::size_t pos;
40 double value;
41 try {
42 value = std::stod(strValue, &pos);
43 } catch (std::invalid_argument const &exc) {
44 errmsg = "Invalid number provided as timeout: " + strValue;
45 return false;
46 } catch (std::out_of_range const &exc) {
47 errmsg = "Provided timeout out of representable range: " + std::string(exc.what());
48 return false;
49 }
50 if (value < 0) {
51 errmsg = "Provided timeout was negative";
52 return false;
53 }
54 strValue = strValue.substr(pos);
55 char unit[3] = {'\0', '\0', '\0'};
56 if (!strValue.empty()) {
57 unit[0] = strValue[0];
58 if (unit[0] >= '0' && unit[0] <= '9') {unit[0] = '\0';}
59 }
60 if (strValue.size() > 1) {
61 unit[1] = strValue[1];
62 if (unit[1] >= '0' && unit[1] <= '9') {unit[1] = '\0';}
63 }
64 if (!strncmp(unit, "ns", 2)) {
65 ts.tv_nsec += value;
66 } else if (!strncmp(unit, "us", 2)) {
67 auto value_s = (static_cast<long long>(value)) / 1'000'000;
68 ts.tv_sec += value_s;
69 value -= value_s * 1'000'000;
70 ts.tv_nsec += value * 1'000'000;
71 } else if (!strncmp(unit, "ms", 2)) {
72 auto value_s = (static_cast<long long>(value)) / 1'000;
73 ts.tv_sec += value_s;
74 value -= value_s * 1'000;
75 ts.tv_nsec += value * 1'000'000;
76 } else if (!strncmp(unit, "s", 1)) {
77 auto value_s = (static_cast<long long>(value));
78 ts.tv_sec += value_s;
79 value -= value_s;
80 ts.tv_nsec += value * 1'000'000'000;
81 } else if (!strncmp(unit, "m", 1)) {
82 value *= 60;
83 auto value_s = (static_cast<long long>(value));
84 ts.tv_sec += value_s;
85 value -= value_s;
86 ts.tv_nsec += value * 1'000'000'000;
87 } else if (!strncmp(unit, "h", 1)) {
88 value *= 3600;
89 auto value_s = (static_cast<long long>(value));
90 ts.tv_sec += value_s;
91 value -= value_s;
92 ts.tv_nsec += value * 1'000'000'000;
93 } else if (strlen(unit) > 0) {
94 errmsg = "Unknown unit in duration: " + std::string(unit);
95 return false;
96 } else {
97 errmsg = "Unit missing from duration: " + duration;
98 return false;
99 }
100 if (ts.tv_nsec > 1'000'000'000) {
101 ts.tv_sec += ts.tv_nsec / 1'000'000'000;
102 ts.tv_nsec = ts.tv_nsec % 1'000'000'000;
103 }
104 strValue = strValue.substr(strlen(unit));
105 }
106 result.tv_nsec = ts.tv_nsec;
107 result.tv_sec = ts.tv_sec;
108 return true;
109}
110
111std::string XrdClHttp::MarshalDuration(const struct timespec &duration)
112{
113 if (duration.tv_sec == 0 && duration.tv_nsec == 0) {return "0s";}
114
115 std::string result = duration.tv_sec != 0 ? std::to_string(duration.tv_sec) + "s" : "";
116 if (duration.tv_nsec) {
117 result += std::to_string(duration.tv_nsec / 1'000'000) + "ms";
118 }
119 return result;
120}
static std::string ts()
timestamp output for logging messages
Definition XrdCephOss.cc:53
bool ParseTimeout(const std::string &duration, struct timespec &, std::string &errmsg)
std::string MarshalDuration(const struct timespec &timeout)