XRootD
Loading...
Searching...
No Matches
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
35class XrdJob;
36struct XrdOucIOVec;
37
38namespace XrdPfc
39{
40class File;
43class IO;
44
45struct ReadVBlockListRAM;
46struct ReadVChunkListRAM;
47struct ReadVBlockListDisk;
48struct 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.
54constexpr int kReadPending = INT_MIN + 1;
55
57{
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{
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
79
81 bool m_sync_done = false;
82 bool m_direct_done = true;
83
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; }
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
108using vChunkRequest_t = std::vector<ChunkRequest>;
109using vChunkRequest_i = std::vector<ChunkRequest>::iterator;
110
111// ================================================================
112
113class Block
114{
115public:
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;
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),
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
173using BlockList_t = std::list<Block*>;
174using BlockList_i = std::list<Block*>::iterator;
175
176// ================================================================
177
179{
180public:
182
184
185 void Done(int result) override;
186};
187
188// ----------------------------------------------------------------
189
191{
192public:
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
209class File
210{
211 friend class Cache;
214public:
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 //----------------------------------------------------------------------
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
300private:
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
431inline void File::inc_ref_count(Block* b)
432{
433 // Method always called under lock.
434 b->m_refcnt++;
435}
436
437//------------------------------------------------------------------------------
438
439inline 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
void Done(int result) override
int get_size() const
int get_error() const
int get_n_cksum_errors()
int * ptr_n_cksum_errors()
Block(File *f, IO *io, void *rid, char *buf, long long off, int size, int rsize, bool m_prefetch, bool cks_net)
IO * get_io() const
vCkSum_t & ref_cksum_vec()
long long get_offset() const
vChunkRequest_t m_chunk_reqs
bool is_finished() const
bool is_ok() const
void set_error(int err)
void * get_req_id() const
void set_downloaded()
bool req_cksum_net() const
char * get_buff() const
bool has_cksums() const
bool is_failed() const
long long m_offset
File * get_file() const
vCkSum_t m_cksum_vec
void reset_error_and_set_io(IO *io, void *rid)
int get_req_size() const
void Done(int result) override
DirectResponseHandler(File *file, ReadRequest *rreq, int to_wait)
bool FinalizeSyncBeforeExit()
Returns true if any of blocks need sync. Called from Cache::dec_ref_cnt on zero ref cnt.
const char * lPath() const
Log path.
int ReadV(IO *io, const XrdOucIOVec *readV, int readVnum, ReadReqRH *rh)
Vector read.
void WriteBlockToDisk(Block *b)
float GetPrefetchScore() const
friend class BlockResponseHandler
int GetNBlocks() const
void StopPrefetchingOnIO(IO *io)
std::string GetRemoteLocations() const
size_t GetAccessCnt() const
int Fstat(struct stat &sbuff)
void AddIO(IO *io)
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.
void RequestSyncOfDetachStats()
Flags that detach stats should be written out in final sync. Called from CacheIO upon Detach.
long long GetPrefetchedBytes() const
int GetBlockSize() const
int GetNDownloadedBlocks() const
const Info::AStat * GetLastAccessStats() const
void BlocksRemovedFromWriteQ(std::list< Block * > &)
Handle removal of a set of blocks from Cache's write queue.
friend class DirectResponseHandler
int inc_ref_cnt()
int GetPrefetchCountOnIO(IO *io)
const Stats & RefStats() const
void Sync()
Sync file cache inf o and output data with disk.
XrdSysTrace * GetTrace() const
int dec_ref_cnt()
int get_ref_cnt()
void ioUpdated(IO *io)
Notification from IO that it has been updated (remote open).
long long initiate_emergency_shutdown()
long long GetFileSize() const
const std::string & GetLocalPath() const
void RemoveIO(IO *io)
friend class Cache
void BlockRemovedFromWriteQ(Block *)
Handle removal of a block from Cache's write queue.
bool is_in_emergency_shutdown()
XrdSysError * GetLog() const
bool ioActive(IO *io)
Initiate close. Return true if still IO active. Used in XrdPosixXrootd::Close()
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
Statistics of cache utilisation by a File object.
std::list< Block * > BlockList_t
std::vector< ChunkRequest >::iterator vChunkRequest_i
constexpr int kReadPending
Definition XrdPfcFile.hh:54
std::vector< ChunkRequest > vChunkRequest_t
std::vector< uint32_t > vCkSum_t
std::list< Block * >::iterator BlockList_i
ChunkRequest(ReadRequest *rreq, char *buf, long long off, int size)
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
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