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 
154  size_t getMaxRanges() const;
155 
161  bool isFullFile();
162 
169  bool isSingleRange();
170 
181 
195  const XrdHttpIOList &NextReadList();
196 
201  void NotifyError();
202 
220  int NotifyReadResult(const ssize_t ret,
221  const UserRange** const urp,
222  bool &start,
223  bool &allend);
224 
233  void ParseContentRange(const char* const line);
234 
238  void reset();
239 
251  int SetFilesize(const off_t sz);
252 
253 private:
254  int parseOneRange(char* const str);
255  int rangeFig(const char* const s, bool &set, off_t &start);
256  void resolveRanges();
257  void splitRanges();
258  void trimSplit();
259 
260  Error error_;
261 
262  UserRangeList rawUserRanges_;
263 
264  bool rangesResolved_;
265 
266  UserRangeList resolvedUserRanges_;
267 
268  XrdHttpIOList splitRange_;
269 
270  // the position in resolvedUserRanges_ corresponding to all the
271  // bytes notified via the NotifyReadResult() method
272  size_t resolvedRangeIdx_;
273  off_t resolvedRangeOff_;
274 
275  // position of the method splitRanges() in within resolvedUserRanges_
276  // from where it split ranges into chunks for sending to read/readv
277  size_t splitRangeIdx_;
278  off_t splitRangeOff_;
279 
280  // the position in splitRange_ corresponding to all the
281  // bytes notified via the NotifyReadResult() method
282  size_t currSplitRangeIdx_;
283  int currSplitRangeOff_;
284 
285  off_t filesize_;
286 
287  size_t vectorReadMaxChunkSize_;
288  size_t vectorReadMaxChunks_;
289  size_t rRequestMaxBytes_;
290 };
291 
292 
293 #endif //XROOTD_XRDHTTPREADRANGEHANDLER_HH
Utility functions for XrdHTTP.
std::vector< XrdOucIOVec2 > XrdHttpIOList
@ Error
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.
size_t getMaxRanges() const
return the maximum number of ranges that may be requested
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)