XRootD
XrdPfcFile.hh
Go to the documentation of this file.
1 #ifndef __XRDPFC_FILE_HH__
2 #define __XRDPFC_FILE_HH__
3 //----------------------------------------------------------------------------------
4 // Copyright (c) 2014 by Board of Trustees of the Leland Stanford, Jr., University
5 // Author: Alja Mrak-Tadel, Matevz Tadel
6 //----------------------------------------------------------------------------------
7 // XRootD is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Lesser General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // XRootD is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
19 //----------------------------------------------------------------------------------
20 
21 #include "XrdPfcTypes.hh"
22 #include "XrdPfcInfo.hh"
23 #include "XrdPfcStats.hh"
24 
25 #include "XrdOuc/XrdOucCache.hh"
26 #include "XrdOuc/XrdOucIOVec.hh"
27 
28 #include <climits>
29 #include <functional>
30 #include <list>
31 #include <map>
32 #include <set>
33 #include <string>
34 
35 class XrdJob;
36 struct XrdOucIOVec;
37 
38 namespace XrdPfc
39 {
40 class File;
41 class BlockResponseHandler;
42 class DirectResponseHandler;
43 class IO;
44 
45 struct ReadVBlockListRAM;
46 struct ReadVChunkListRAM;
47 struct ReadVBlockListDisk;
48 struct ReadVChunkListDisk;
49 
50 // Returned by File::Read()/ReadV() when the request is queued and its ReadReqRH will
51 // be called later. Must not be a -errno: the former -EWOULDBLOCK equals -EAGAIN on
52 // Linux, so a read that failed with EAGAIN was mistaken for a pending one. Not
53 // INT_MIN itself, so that negating it, as error paths do, stays well defined.
54 constexpr int kReadPending = INT_MIN + 1;
55 
56 struct ReadReqRH : public XrdOucCacheIOCB
57 {
58  int m_expected_size = 0;
59  int m_n_chunks = 0; // Only set for ReadV().
60  unsigned short m_seq_id;
61  XrdOucCacheIOCB *m_iocb; // External callback passed into IO::Read().
62 
63  ReadReqRH(unsigned short sid, XrdOucCacheIOCB *iocb) :
64  m_seq_id(sid), m_iocb(iocb)
65  {}
66 };
67 
68 // -------------------------------------------------------------
69 
71 {
72  IO *m_io;
73  ReadReqRH *m_rh; // Internal callback created in IO::Read().
74 
75  long long m_bytes_read = 0;
76  int m_error_cond = 0; // to be set to -errno
77  int m_error_count = 0;
79 
80  int m_n_chunk_reqs = 0;
81  bool m_sync_done = false;
82  bool m_direct_done = true;
83 
84  ReadRequest(IO *io, ReadReqRH *rh) :
85  m_io(io), m_rh(rh)
86  {}
87 
89 
90  bool is_complete() const { return m_n_chunk_reqs == 0 && m_sync_done && m_direct_done; }
91  int return_value() const { return m_error_cond ? m_error_cond : m_bytes_read; }
92 };
93 
94 // -------------------------------------------------------------
95 
97 {
99  char *m_buf; // Where to place the data chunk.
100  long long m_off; // Offset *within* the corresponding block.
101  int m_size; // Size of the data chunk.
102 
103  ChunkRequest(ReadRequest *rreq, char *buf, long long off, int size) :
104  m_read_req(rreq), m_buf(buf), m_off(off), m_size(size)
105  {}
106 };
107 
108 using vChunkRequest_t = std::vector<ChunkRequest>;
109 using vChunkRequest_i = std::vector<ChunkRequest>::iterator;
110 
111 // ================================================================
112 
113 class Block
114 {
115 public:
117  IO *m_io; // IO that handled current request, used for == / != comparisons only
118  void *m_req_id; // Identity of requestor -- used for stats.
119 
120  char *m_buff;
121  long long m_offset;
122  int m_size;
124  int m_refcnt;
125  int m_errno; // stores negative errno
131 
133 
134  Block(File *f, IO *io, void *rid, char *buf, long long off, int size, int rsize,
135  bool m_prefetch, bool cks_net) :
136  m_file(f), m_io(io), m_req_id(rid),
137  m_buff(buf), m_offset(off), m_size(size), m_req_size(rsize),
139  m_req_cksum_net(cks_net), m_n_cksum_errors(0)
140  {}
141 
142  char* get_buff() const { return m_buff; }
143  int get_size() const { return m_size; }
144  int get_req_size() const { return m_req_size; }
145  long long get_offset() const { return m_offset; }
146 
147  File* get_file() const { return m_file; }
148  IO* get_io() const { return m_io; }
149  void* get_req_id() const { return m_req_id; }
150 
151  bool is_finished() const { return m_downloaded || m_errno != 0; }
152  bool is_ok() const { return m_downloaded; }
153  bool is_failed() const { return m_errno != 0; }
154 
155  void set_downloaded() { m_downloaded = true; }
156  void set_error(int err) { m_errno = err; }
157  int get_error() const { return m_errno; }
158 
159  void reset_error_and_set_io(IO *io, void *rid)
160  {
161  m_errno = 0;
162  m_io = io;
163  m_req_id = rid;
164  }
165 
166  bool req_cksum_net() const { return m_req_cksum_net; }
167  bool has_cksums() const { return ! m_cksum_vec.empty(); }
171 };
172 
173 using BlockList_t = std::list<Block*>;
174 using BlockList_i = std::list<Block*>::iterator;
175 
176 // ================================================================
177 
179 {
180 public:
182 
184 
185  void Done(int result) override;
186 };
187 
188 // ----------------------------------------------------------------
189 
191 {
192 public:
197  int m_bytes_read = 0;
198  int m_errno = 0;
199 
200  DirectResponseHandler(File *file, ReadRequest *rreq, int to_wait) :
201  m_file(file), m_read_req(rreq), m_to_wait(to_wait)
202  {}
203 
204  void Done(int result) override;
205 };
206 
207 // ================================================================
208 
209 class File
210 {
211  friend class Cache;
212  friend class BlockResponseHandler;
213  friend class DirectResponseHandler;
214 public:
215  // Constructor, destructor, Open() and Close() are private.
216 
218  static File* FileOpen(const std::string &path, long long offset, long long fileSize, XrdOucCacheIO* inputIO);
219 
222 
224  void BlocksRemovedFromWriteQ(std::list<Block*>&);
225 
227  int Read(IO *io, char* buff, long long offset, int size, ReadReqRH *rh);
228 
230  int ReadV(IO *io, const XrdOucIOVec *readV, int readVnum, ReadReqRH *rh);
231 
232  //----------------------------------------------------------------------
234  //----------------------------------------------------------------------
235  void ioUpdated(IO *io);
236 
237  //----------------------------------------------------------------------
240  //----------------------------------------------------------------------
241  bool ioActive(IO *io);
242 
243  //----------------------------------------------------------------------
246  //----------------------------------------------------------------------
248 
249  //----------------------------------------------------------------------
252  //----------------------------------------------------------------------
253  bool FinalizeSyncBeforeExit();
254 
255  //----------------------------------------------------------------------
257  //----------------------------------------------------------------------
258  void Sync();
259 
260  void WriteBlockToDisk(Block* b);
261 
262  void Prefetch();
263 
264  float GetPrefetchScore() const;
265 
267  const char* lPath() const;
268 
269  const std::string& GetLocalPath() const { return m_filename; }
270 
271  XrdSysError* GetLog() const;
272  XrdSysTrace* GetTrace() const;
273 
274  long long GetFileSize() const { return m_file_size; }
275 
276  void AddIO(IO *io);
279  void RemoveIO(IO *io);
280 
281  std::string GetRemoteLocations() const;
282  const Info::AStat* GetLastAccessStats() const { return m_cfi.GetLastAccessStats(); }
283  size_t GetAccessCnt() const { return m_cfi.GetAccessCnt(); }
284  int GetBlockSize() const { return m_cfi.GetBufferSize(); }
285  int GetNBlocks() const { return m_cfi.GetNBlocks(); }
286  int GetNDownloadedBlocks() const { return m_cfi.GetNDownloadedBlocks(); }
287  long long GetPrefetchedBytes() const { return m_prefetch_bytes; }
288  const Stats& RefStats() const { return m_stats; }
289 
290  int Fstat(struct stat &sbuff);
291 
292  // These three methods are called under Cache's m_active lock
293  int get_ref_cnt() { return m_ref_cnt; }
294  int inc_ref_cnt() { return ++m_ref_cnt; }
295  int dec_ref_cnt() { return --m_ref_cnt; }
296 
297  long long initiate_emergency_shutdown();
298  bool is_in_emergency_shutdown() { return m_in_shutdown; }
299 
300 private:
302  File(const std::string &path, long long offset, long long fileSize);
303 
305  ~File();
306 
308  void Close();
309 
311  bool Open(XrdOucCacheIO* inputIO);
312  void parse_pfc_url_args(XrdOucCacheIO* inputIO, long long &pfc_blocksize, int &pfc_prefetch) const;
313 
314  static const char *m_traceID;
315 
316  int m_ref_cnt;
317 
318  XrdOssDF *m_data_file;
319  XrdOssDF *m_info_file;
320  Info m_cfi;
321 
322  const std::string m_filename;
323  const long long m_offset;
324  const long long m_file_size;
325 
326  // IO objects attached to this file.
327 
328  typedef std::set<IO*> IoSet_t;
329  typedef IoSet_t::iterator IoSet_i;
330 
331  IoSet_t m_io_set;
332  IoSet_i m_current_io;
333  int m_ios_in_detach;
334 
335  // FSync
336 
337  std::vector<int> m_writes_during_sync;
338  int m_non_flushed_cnt;
339  bool m_in_sync;
340  bool m_detach_time_logged;
341  bool m_in_shutdown;
342 
343  // Block state and management
344 
345  typedef std::list<int> IntList_t;
346  typedef IntList_t::iterator IntList_i;
347 
348  typedef std::map<int, Block*> BlockMap_t;
349  typedef BlockMap_t::iterator BlockMap_i;
350 
351  BlockMap_t m_block_map;
352  XrdSysCondVar m_state_cond;
353  long long m_block_size;
354  int m_num_blocks;
355 
356  // Stats and ResourceMonitor interface
357 
358  Stats m_stats;
359  Stats m_delta_stats;
360  long long m_st_blocks;
361  long long m_resmon_report_threshold;
362  int m_resmon_token;
363 
364  void check_delta_stats();
365  void report_and_merge_delta_stats();
366 
367  std::set<std::string> m_remote_locations;
368  void insert_remote_location(const std::string &loc);
369 
370  // Prefetch
371 
372  enum PrefetchState_e { kOff=-1, kOn, kHold, kStopped, kComplete };
373 
374  PrefetchState_e m_prefetch_state;
375  int m_prefetch_max_blocks_in_flight;
376 
377  long long m_prefetch_bytes;
378  int m_prefetch_read_cnt;
379  int m_prefetch_hit_cnt;
380  float m_prefetch_score; // cached
381 
382  void inc_prefetch_read_cnt(int prc) { if (prc) { m_prefetch_read_cnt += prc; calc_prefetch_score(); } }
383  void inc_prefetch_hit_cnt (int phc) { if (phc) { m_prefetch_hit_cnt += phc; calc_prefetch_score(); } }
384  void calc_prefetch_score() { m_prefetch_score = float(m_prefetch_hit_cnt) / m_prefetch_read_cnt; }
385 
386  // Helpers
387 
388  bool overlap(int blk, // block to query
389  long long blk_size, //
390  long long req_off, // offset of user request
391  int req_size, // size of user request
392  // output:
393  long long &off, // offset in user buffer
394  long long &blk_off, // offset in block
395  int &size);
396 
397  // Read & ReadV
398 
399  Block* PrepareBlockRequest(int i, IO *io, void *req_id, bool prefetch);
400 
401  void ProcessBlockRequest (Block *b);
402  void ProcessBlockRequests(BlockList_t& blks);
403 
404  void RequestBlocksDirect(IO *io, ReadRequest *read_req, std::vector<XrdOucIOVec>& ioVec, int expected_size);
405 
406  int ReadBlocksFromDisk(std::vector<XrdOucIOVec>& ioVec, int expected_size);
407 
408  int ReadOpusCoalescere(IO *io, const XrdOucIOVec *readV, int readVnum,
409  ReadReqRH *rh, const char *tpfx);
410 
411  void ProcessDirectReadFinished(ReadRequest *rreq, int bytes_read, int error_cond);
412  void ProcessBlockError(Block *b, ReadRequest *rreq);
413  void ProcessBlockSuccess(Block *b, ChunkRequest &creq);
414  void FinalizeReadRequest(ReadRequest *rreq);
415 
416  void ProcessBlockResponse(Block *b, int res);
417 
418  // Block management
419 
420  void inc_ref_count(Block* b);
421  void dec_ref_count(Block* b, int count = 1);
422  void free_block(Block*);
423 
424  bool select_current_io_or_disable_prefetching(bool skip_current);
425 
426  int offsetIdx(int idx) const;
427 };
428 
429 //------------------------------------------------------------------------------
430 
431 inline void File::inc_ref_count(Block* b)
432 {
433  // Method always called under lock.
434  b->m_refcnt++;
435 }
436 
437 //------------------------------------------------------------------------------
438 
439 inline void File::dec_ref_count(Block* b, int count)
440 {
441  // Method always called under lock.
442  assert(b->is_finished());
443  b->m_refcnt -= count;
444  assert(b->m_refcnt >= 0);
445 
446  if (b->m_refcnt == 0)
447  {
448  free_block(b);
449  }
450 }
451 
452 }
453 
454 #endif
#define stat(a, b)
Definition: XrdPosix.hh:101
XrdOucString File
Definition: XrdJob.hh:43
void Done(int result) override
Definition: XrdPfcFile.cc:1753
int * ptr_n_cksum_errors()
Definition: XrdPfcFile.hh:170
int get_size() const
Definition: XrdPfcFile.hh:143
int get_error() const
Definition: XrdPfcFile.hh:157
int get_n_cksum_errors()
Definition: XrdPfcFile.hh:169
Block(File *f, IO *io, void *rid, char *buf, long long off, int size, int rsize, bool m_prefetch, bool cks_net)
Definition: XrdPfcFile.hh:134
void * get_req_id() const
Definition: XrdPfcFile.hh:149
long long get_offset() const
Definition: XrdPfcFile.hh:145
vChunkRequest_t m_chunk_reqs
Definition: XrdPfcFile.hh:132
bool is_finished() const
Definition: XrdPfcFile.hh:151
bool is_ok() const
Definition: XrdPfcFile.hh:152
void set_error(int err)
Definition: XrdPfcFile.hh:156
vCkSum_t & ref_cksum_vec()
Definition: XrdPfcFile.hh:168
int m_n_cksum_errors
Definition: XrdPfcFile.hh:130
char * get_buff() const
Definition: XrdPfcFile.hh:142
IO * get_io() const
Definition: XrdPfcFile.hh:148
void set_downloaded()
Definition: XrdPfcFile.hh:155
bool req_cksum_net() const
Definition: XrdPfcFile.hh:166
void * m_req_id
Definition: XrdPfcFile.hh:118
bool has_cksums() const
Definition: XrdPfcFile.hh:167
File * get_file() const
Definition: XrdPfcFile.hh:147
bool is_failed() const
Definition: XrdPfcFile.hh:153
long long m_offset
Definition: XrdPfcFile.hh:121
vCkSum_t m_cksum_vec
Definition: XrdPfcFile.hh:129
void reset_error_and_set_io(IO *io, void *rid)
Definition: XrdPfcFile.hh:159
bool m_req_cksum_net
Definition: XrdPfcFile.hh:128
int get_req_size() const
Definition: XrdPfcFile.hh:144
Attaches/creates and detaches/deletes cache-io objects for disk based cache.
Definition: XrdPfc.hh:165
void Done(int result) override
Definition: XrdPfcFile.cc:1761
DirectResponseHandler(File *file, ReadRequest *rreq, int to_wait)
Definition: XrdPfcFile.hh:200
bool FinalizeSyncBeforeExit()
Returns true if any of blocks need sync. Called from Cache::dec_ref_cnt on zero ref cnt.
Definition: XrdPfcFile.cc:325
const char * lPath() const
Log path.
Definition: XrdPfcFile.cc:1609
int ReadV(IO *io, const XrdOucIOVec *readV, int readVnum, ReadReqRH *rh)
Vector read.
Definition: XrdPfcFile.cc:854
void WriteBlockToDisk(Block *b)
Definition: XrdPfcFile.cc:1137
float GetPrefetchScore() const
Definition: XrdPfcFile.cc:1697
int GetNBlocks() const
Definition: XrdPfcFile.hh:285
void Prefetch()
Definition: XrdPfcFile.cc:1624
void StopPrefetchingOnIO(IO *io)
std::string GetRemoteLocations() const
Definition: XrdPfcFile.cc:1721
const Info::AStat * GetLastAccessStats() const
Definition: XrdPfcFile.hh:282
size_t GetAccessCnt() const
Definition: XrdPfcFile.hh:283
int Fstat(struct stat &sbuff)
Definition: XrdPfcFile.cc:632
void AddIO(IO *io)
Definition: XrdPfcFile.cc:349
static File * FileOpen(const std::string &path, long long offset, long long fileSize, XrdOucCacheIO *inputIO)
Static constructor that also does Open. Returns null ptr if Open fails.
Definition: XrdPfcFile.cc:141
void RequestSyncOfDetachStats()
Flags that detach stats should be written out in final sync. Called from CacheIO upon Detach.
Definition: XrdPfcFile.cc:319
long long GetPrefetchedBytes() const
Definition: XrdPfcFile.hh:287
int GetBlockSize() const
Definition: XrdPfcFile.hh:284
int GetNDownloadedBlocks() const
Definition: XrdPfcFile.hh:286
void BlocksRemovedFromWriteQ(std::list< Block * > &)
Handle removal of a set of blocks from Cache's write queue.
Definition: XrdPfcFile.cc:219
int inc_ref_cnt()
Definition: XrdPfcFile.hh:294
int GetPrefetchCountOnIO(IO *io)
void Sync()
Sync file cache inf o and output data with disk.
Definition: XrdPfcFile.cc:1223
XrdSysTrace * GetTrace() const
Definition: XrdPfcFile.cc:1707
int dec_ref_cnt()
Definition: XrdPfcFile.hh:295
int get_ref_cnt()
Definition: XrdPfcFile.hh:293
int Read(IO *io, char *buff, long long offset, int size, ReadReqRH *rh)
Normal read.
Definition: XrdPfcFile.cc:817
void ioUpdated(IO *io)
Notification from IO that it has been updated (remote open).
Definition: XrdPfcFile.cc:233
long long initiate_emergency_shutdown()
Definition: XrdPfcFile.cc:154
long long GetFileSize() const
Definition: XrdPfcFile.hh:274
const Stats & RefStats() const
Definition: XrdPfcFile.hh:288
void RemoveIO(IO *io)
Definition: XrdPfcFile.cc:386
void BlockRemovedFromWriteQ(Block *)
Handle removal of a block from Cache's write queue.
Definition: XrdPfcFile.cc:211
const std::string & GetLocalPath() const
Definition: XrdPfcFile.hh:269
bool is_in_emergency_shutdown()
Definition: XrdPfcFile.hh:298
XrdSysError * GetLog() const
Definition: XrdPfcFile.cc:1702
bool ioActive(IO *io)
Initiate close. Return true if still IO active. Used in XrdPosixXrootd::Close()
Definition: XrdPfcFile.cc:242
Base cache-io class that implements some XrdOucCacheIO abstract methods.
Definition: XrdPfcIO.hh:16
Status of cached file. Can be read from and written into a binary file.
Definition: XrdPfcInfo.hh:41
const AStat * GetLastAccessStats() const
Get latest access stats.
Definition: XrdPfcInfo.cc:489
long long GetBufferSize() const
Get prefetch buffer size.
Definition: XrdPfcInfo.hh:469
int GetNDownloadedBlocks() const
Get number of downloaded blocks.
Definition: XrdPfcInfo.hh:398
size_t GetAccessCnt() const
Get number of accesses.
Definition: XrdPfcInfo.hh:261
int GetNBlocks() const
Get number of blocks represented in download-state bit-vector.
Definition: XrdPfcInfo.hh:437
Statistics of cache utilisation by a File object.
Definition: XrdPfcStats.hh:35
OpenImpl< false > Open(Ctx< File > file, Arg< std::string > url, Arg< OpenFlags::Flags > flags, Arg< Access::Mode > mode=Access::None, uint16_t timeout=0)
Factory for creating ReadImpl objects.
CloseImpl< false > Close(Ctx< File > file, uint16_t timeout=0)
Factory for creating CloseImpl objects.
Definition: XrdPfc.hh:41
std::vector< ChunkRequest > vChunkRequest_t
Definition: XrdPfcFile.hh:108
std::vector< ChunkRequest >::iterator vChunkRequest_i
Definition: XrdPfcFile.hh:109
constexpr int kReadPending
Definition: XrdPfcFile.hh:54
std::list< Block * > BlockList_t
Definition: XrdPfcFile.hh:173
std::vector< uint32_t > vCkSum_t
Definition: XrdPfcTypes.hh:31
std::list< Block * >::iterator BlockList_i
Definition: XrdPfcFile.hh:174
ChunkRequest(ReadRequest *rreq, char *buf, long long off, int size)
Definition: XrdPfcFile.hh:103
ReadRequest * m_read_req
Definition: XrdPfcFile.hh:98
Access statistics.
Definition: XrdPfcInfo.hh:57
XrdOucCacheIOCB * m_iocb
Definition: XrdPfcFile.hh:61
unsigned short m_seq_id
Definition: XrdPfcFile.hh:60
ReadReqRH(unsigned short sid, XrdOucCacheIOCB *iocb)
Definition: XrdPfcFile.hh:63
void update_error_cond(int ec)
Definition: XrdPfcFile.hh:88
ReadRequest(IO *io, ReadReqRH *rh)
Definition: XrdPfcFile.hh:84
ReadReqRH * m_rh
Definition: XrdPfcFile.hh:73
bool is_complete() const
Definition: XrdPfcFile.hh:90
int return_value() const
Definition: XrdPfcFile.hh:91
long long m_bytes_read
Definition: XrdPfcFile.hh:75