XRootD
XrdHttpReadRangeHandler.hh
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // This file is part of XrdHTTP: A pragmatic implementation of the
3 // HTTP/WebDAV protocol for the Xrootd framework
4 //
5 // Copyright (c) 2013 by European Organization for Nuclear Research (CERN)
6 // Authors: Cedric Caffy <ccaffy@cern.ch>, David Smith
7 // File Date: Aug 2023
8 //------------------------------------------------------------------------------
9 // XRootD is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // XRootD is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
21 //------------------------------------------------------------------------------
22 
23 #ifndef XROOTD_XRDHTTPREADRANGEHANDLER_HH
24 #define XROOTD_XRDHTTPREADRANGEHANDLER_HH
25 
26 #include "XrdHttpUtils.hh"
27 #include <vector>
28 #include <string>
29 
30 
37 public:
38 
45  static constexpr size_t READV_MAXCHUNKS = 512;
46  static constexpr size_t READV_MAXCHUNKSIZE = 512*1024;
47  static constexpr size_t RREQ_MAXSIZE = 8*1024*1024;
48 
54  struct Configuration {
55  Configuration() : haveSizes(false) { }
56 
57  Configuration(const size_t vectorReadMaxChunkSize,
58  const size_t vectorReadMaxChunks,
59  const size_t rRequestMaxBytes) :
60  haveSizes(true), readv_ior_max(vectorReadMaxChunkSize),
61  readv_iov_max(vectorReadMaxChunks), reqs_max(rRequestMaxBytes) { }
62 
63 
64  bool haveSizes;
65  size_t readv_ior_max; // max chunk size
66  size_t readv_iov_max; // max number of chunks
67  size_t reqs_max; // max bytes in read or readv
68  };
69 
74  struct Error {
75  bool errSet{false};
76  int httpRetCode{0};
77  std::string errMsg;
78 
79  explicit operator bool() const { return errSet; }
80 
81  void set(int rc, const std::string &m)
82  { httpRetCode = rc; errMsg = m; errSet = true; }
83 
84  void reset() { httpRetCode = 0; errMsg.clear(); errSet = false; }
85  };
86 
91  struct UserRange {
92  bool start_set;
93  bool end_set;
94  off_t start;
95  off_t end;
96 
97  UserRange() : start_set(false), end_set(false), start(0), end(0) { }
98 
99  UserRange(off_t st, off_t en) : start_set(true), end_set(true), start(st),
100  end(en) { }
101  };
102 
103  typedef std::vector<UserRange> UserRangeList;
104 
114  {
115  rRequestMaxBytes_ = RREQ_MAXSIZE;
116  vectorReadMaxChunkSize_ = READV_MAXCHUNKSIZE;
117  vectorReadMaxChunks_ = READV_MAXCHUNKS;
118 
119  if( conf.haveSizes )
120  {
121  vectorReadMaxChunkSize_ = conf.readv_ior_max;
122  vectorReadMaxChunks_ = conf.readv_iov_max;
123  rRequestMaxBytes_ = conf.reqs_max;
124  }
125  reset();
126  }
127 
135  static int Configure(XrdSysError &Eroute, const char *const parms,
136  Configuration &cfg);
137 
143  const Error& getError() const;
144 
150  bool isFullFile();
151 
158  bool isSingleRange();
159 
170 
184  const XrdHttpIOList &NextReadList();
185 
190  void NotifyError();
191 
209  int NotifyReadResult(const ssize_t ret,
210  const UserRange** const urp,
211  bool &start,
212  bool &allend);
213 
222  void ParseContentRange(const char* const line);
223 
227  void reset();
228 
240  int SetFilesize(const off_t sz);
241 
242 private:
243  int parseOneRange(char* const str);
244  int rangeFig(const char* const s, bool &set, off_t &start);
245  void resolveRanges();
246  void splitRanges();
247  void trimSplit();
248 
249  Error error_;
250 
251  UserRangeList rawUserRanges_;
252 
253  bool rangesResolved_;
254 
255  UserRangeList resolvedUserRanges_;
256 
257  XrdHttpIOList splitRange_;
258 
259  // the position in resolvedUserRanges_ corresponding to all the
260  // bytes notified via the NotifyReadResult() method
261  size_t resolvedRangeIdx_;
262  off_t resolvedRangeOff_;
263 
264  // position of the method splitRanges() in within resolvedUserRanges_
265  // from where it split ranges into chunks for sending to read/readv
266  size_t splitRangeIdx_;
267  off_t splitRangeOff_;
268 
269  // the position in splitRange_ corresponding to all the
270  // bytes notified via the NotifyReadResult() method
271  size_t currSplitRangeIdx_;
272  int currSplitRangeOff_;
273 
274  off_t filesize_;
275 
276  size_t vectorReadMaxChunkSize_;
277  size_t vectorReadMaxChunks_;
278  size_t rRequestMaxBytes_;
279 };
280 
281 
282 #endif //XROOTD_XRDHTTPREADRANGEHANDLER_HH
Utility functions for XrdHTTP.
std::vector< XrdOucIOVec2 > XrdHttpIOList
Definition: XrdHttpUtils.hh:95
static constexpr size_t READV_MAXCHUNKSIZE
void reset()
resets this handler
const XrdHttpIOList & NextReadList()
return XrdHttpIOList for sending to read or readv
void ParseContentRange(const char *const line)
parse the line after a "Range: " http request header
int SetFilesize(const off_t sz)
sets the filesize, used during resolving and issuing range requests
XrdHttpReadRangeHandler(const Configuration &conf)
static int Configure(XrdSysError &Eroute, const char *const parms, Configuration &cfg)
void NotifyError()
Force handler to enter error state.
bool isFullFile()
indicates when there were no valid Range head ranges supplied
std::vector< UserRange > UserRangeList
int NotifyReadResult(const ssize_t ret, const UserRange **const urp, bool &start, bool &allend)
Advance internal counters concerning received bytes.
const Error & getError() const
return the Error object
bool isSingleRange()
indicates a single range (implied whole file, or single range) or empty file
static constexpr size_t RREQ_MAXSIZE
static constexpr size_t READV_MAXCHUNKS
const UserRangeList & ListResolvedRanges()
return resolved (i.e. obsolute start and end) byte ranges desired
Configuration(const size_t vectorReadMaxChunkSize, const size_t vectorReadMaxChunks, const size_t rRequestMaxBytes)
void set(int rc, const std::string &m)