37 #include <unordered_map>
46 const int BLOCK_WRITE_MAX_ATTEMPTS = 4;
52 const char *File::m_traceID =
"File";
56 File::File(
const std::string& path,
long long iOffset,
long long iFileSize) :
60 m_cfi(
Cache::TheOne().GetTrace(),
Cache::TheOne().is_prefetch_enabled()),
63 m_file_size(iFileSize),
64 m_current_io(m_io_set.end()),
68 m_detach_time_logged(false),
74 m_prefetch_state(kOff),
76 m_prefetch_read_cnt(0),
77 m_prefetch_hit_cnt(0),
104 m_info_file->
Close();
106 m_info_file =
nullptr;
112 m_data_file->
Close();
114 m_data_file =
nullptr;
117 if (m_resmon_token >= 0)
125 if (sr == 0 && s.st_blocks != m_st_blocks) {
128 m_st_blocks = s.st_blocks;
136 TRACEF(
Debug,
"Close() finished, prefetch score = " << m_prefetch_score);
143 File *file =
new File(path, offset, fileSize);
144 if ( ! file->Open(inputIO))
169 m_in_shutdown =
true;
171 if (m_prefetch_state != kStopped && m_prefetch_state != kComplete)
173 m_prefetch_state = kStopped;
174 cache()->DeRegisterPrefetchFile(
this);
177 report_and_merge_delta_stats();
184 void File::check_delta_stats()
189 report_and_merge_delta_stats();
192 void File::report_and_merge_delta_stats()
196 m_data_file->
Fstat(&s);
199 long long max_st_blocks_to_report = (m_file_size & 0xfff) ? ((m_file_size >> 12) + 1) << 3
201 long long st_blocks_to_report = std::min((
long long) s.st_blocks, max_st_blocks_to_report);
203 m_st_blocks = st_blocks_to_report;
205 m_stats.
AddUp(m_delta_stats);
206 m_delta_stats.
Reset();
213 TRACEF(Dump,
"BlockRemovedFromWriteQ() block = " << (
void*) b <<
" idx= " << b->
m_offset/m_block_size);
221 TRACEF(Dump,
"BlocksRemovedFromWriteQ() n_blocks = " << blocks.size());
225 for (std::list<Block*>::iterator i = blocks.begin(); i != blocks.end(); ++i)
237 insert_remote_location(loc);
253 IoSet_i mi = m_io_set.find(io);
255 if (mi != m_io_set.end())
260 ", active_reads " << n_active_reads <<
261 ", active_prefetches " << io->m_active_prefetches <<
262 ", allow_prefetching " << io->m_allow_prefetching <<
263 ", ios_in_detach " << m_ios_in_detach);
265 "\tio_map.size() " << m_io_set.size() <<
266 ", block_map.size() " << m_block_map.size() <<
", file");
268 insert_remote_location(loc);
270 io->m_allow_prefetching =
false;
271 io->m_in_detach =
true;
274 if (m_prefetch_state == kOn || m_prefetch_state == kHold)
276 if ( ! select_current_io_or_disable_prefetching(
false) )
278 TRACEF(
Debug,
"ioActive stopping prefetching after io " << io <<
" retreat.");
285 bool io_active_result;
287 if (n_active_reads > 0)
289 io_active_result =
true;
291 else if (m_io_set.size() - m_ios_in_detach == 1)
293 io_active_result = ! m_block_map.empty();
297 io_active_result = io->m_active_prefetches > 0;
300 if ( ! io_active_result)
305 TRACEF(
Info,
"ioActive for io " << io <<
" returning " << io_active_result <<
", file");
307 return io_active_result;
311 TRACEF(
Error,
"ioActive io " << io <<
" not found in IoSet. This should not happen.");
322 m_detach_time_logged =
false;
331 if ( ! m_in_shutdown)
333 if ( ! m_writes_during_sync.empty() || m_non_flushed_cnt > 0 || ! m_detach_time_logged)
335 report_and_merge_delta_stats();
337 m_detach_time_logged =
true;
339 TRACEF(
Debug,
"FinalizeSyncBeforeExit requesting sync to write detach stats");
343 TRACEF(
Debug,
"FinalizeSyncBeforeExit sync not required");
355 time_t now = time(0);
360 IoSet_i mi = m_io_set.find(io);
362 if (mi == m_io_set.end())
365 io->m_attach_time = now;
368 insert_remote_location(loc);
370 if (m_prefetch_state == kStopped)
372 m_prefetch_state = kOn;
373 cache()->RegisterPrefetchFile(
this);
378 TRACEF(
Error,
"AddIO() io = " << (
void*)io <<
" already registered.");
392 time_t now = time(0);
396 IoSet_i mi = m_io_set.find(io);
398 if (mi != m_io_set.end())
400 if (mi == m_current_io)
405 m_delta_stats.
IoDetach(now - io->m_attach_time);
409 if (m_io_set.empty() && m_prefetch_state != kStopped && m_prefetch_state != kComplete)
411 TRACEF(
Error,
"RemoveIO() io = " << (
void*)io <<
" Prefetching is not stopped/complete -- it should be by now.");
412 m_prefetch_state = kStopped;
413 cache()->DeRegisterPrefetchFile(
this);
418 TRACEF(
Error,
"RemoveIO() io = " << (
void*)io <<
" is NOT registered.");
430 static const char *tpfx =
"Open() ";
432 TRACEF(Dump, tpfx <<
"entered");
443 struct stat data_stat, info_stat;
447 bool data_existed = (myOss.
Stat(m_filename.c_str(), &data_stat) ==
XrdOssOK);
448 bool info_existed = (myOss.
Stat(ifn.c_str(), &info_stat) ==
XrdOssOK);
451 char size_str[32]; sprintf(size_str,
"%lld", m_file_size);
452 myEnv.
Put(
"oss.asize", size_str);
464 m_data_file = myOss.
newFile(myUser);
465 if ((res = m_data_file->
Open(m_filename.c_str(), O_RDWR, 0600, myEnv)) !=
XrdOssOK)
469 delete m_data_file; m_data_file = 0;
470 if ( ! data_existed) myOss.
Unlink(m_filename.c_str());
474 myEnv.
Put(
"oss.asize",
"64k");
480 m_data_file->
Close();
delete m_data_file; m_data_file = 0;
481 if ( ! data_existed) myOss.
Unlink(m_filename.c_str());
485 m_info_file = myOss.
newFile(myUser);
486 if ((res = m_info_file->
Open(ifn.c_str(), O_RDWR, 0600, myEnv)) !=
XrdOssOK)
490 delete m_info_file; m_info_file = 0;
491 m_data_file->
Close();
delete m_data_file; m_data_file = 0;
494 if ( ! info_existed) myOss.
Unlink(ifn.c_str());
495 if ( ! data_existed) myOss.
Unlink(m_filename.c_str());
499 bool initialize_info_file =
true;
501 if (info_existed && m_cfi.
Read(m_info_file, ifn.c_str()))
503 TRACEF(
Debug, tpfx <<
"Reading existing info file. (data_existed=" << data_existed <<
504 ", data_size_stat=" << (data_existed ? data_stat.st_size : -1ll) <<
511 initialize_info_file =
false;
513 TRACEF(
Warning, tpfx <<
"Basic sanity checks on data file failed, resetting info file, truncating data file.");
521 else if (info_existed)
525 TRACEF(
Warning, tpfx <<
"Reading existing info file failed, resetting info file, truncating data file.");
537 TRACEF(
Info, tpfx <<
"Cksum state of file insufficient, uvkeep test failed, resetting info file, truncating data file.");
538 initialize_info_file =
true;
554 parse_pfc_url_args(inputIO, pfc_blocksize, pfc_prefetch);
557 if (initialize_info_file)
562 m_cfi.
Write(m_info_file, ifn.c_str());
563 m_info_file->
Fsync();
564 cache()->WriteFileSizeXAttr(m_info_file->
getFD(), m_file_size);
566 if (data_existed && ! info_existed) {
570 TRACEF(
Debug, tpfx <<
"Creating new file info, data size = " << m_file_size <<
" num blocks = " << m_cfi.
GetNBlocks()
571 <<
" block size = " << pfc_blocksize);
575 if (futimens(m_info_file->
getFD(), NULL)) {
579 TRACEF(
Info, tpfx <<
"URL CGI pfc.blocksize ignored for an already existing file");
587 if (m_resmon_token < 0)
589 TRACEF(
Error, tpfx <<
"no resource-monitor token available, not caching it; "
590 "this indicates a token leak in XrdPfc, please report it.");
591 m_info_file->
Close();
delete m_info_file; m_info_file =
nullptr;
592 m_data_file->
Close();
delete m_data_file; m_data_file =
nullptr;
594 if ( ! info_existed) myOss.
Unlink(ifn.c_str());
595 if ( ! data_existed) myOss.
Unlink(m_filename.c_str());
603 m_prefetch_state = (m_cfi.
IsComplete()) ? kComplete : kStopped;
604 m_prefetch_max_blocks_in_flight = pfc_prefetch;
606 TRACEF(
Debug, tpfx <<
"pfc.prefetch set to " << pfc_prefetch <<
" via CGI parameter");
608 m_data_file->
Fstat(&data_stat);
609 m_st_blocks = data_stat.st_blocks;
611 constexpr
long long MB = 1024 * 1024;
612 m_resmon_report_threshold = std::min(std::max(10 * MB, m_file_size / 20), 500 * MB);
621 void File::parse_pfc_url_args(
XrdOucCacheIO* inputIO,
long long &pfc_blocksize,
int &pfc_prefetch)
const
626 auto const & urlp = url.GetParams();
628 auto extract = [&](
const std::string &key, std::string &value) ->
bool {
629 auto it = urlp.find(key);
630 if (it != urlp.end()) {
642 const char *tpfx =
"File::Open::urlcgi pfc.blocksize ";
647 pfc_blocksize = bsize;
649 TRACEF(
Error, tpfx <<
"Error processing the parameter.");
654 const char *tpfx =
"File::Open::urlcgi pfc.prefetch ";
656 if (
Cache::TheOne().prefetch_str2value(tpfx, val.c_str(), pref,
661 TRACEF(
Error, tpfx <<
"Error processing the parameter.");
679 if ((res = m_data_file->
Fstat(&sbuff)))
return res;
681 sbuff.st_size = m_file_size;
683 bool is_cached = cache()->DecideIfConsideredCached(m_file_size, sbuff.st_blocks * 512ll);
694 bool File::overlap(
int blk,
703 const long long beg = blk * blk_size;
704 const long long end = beg + blk_size;
705 const long long req_end = req_off + req_size;
707 if (req_off < end && req_end > beg)
709 const long long ovlp_beg = std::max(beg, req_off);
710 const long long ovlp_end = std::min(end, req_end);
712 off = ovlp_beg - req_off;
713 blk_off = ovlp_beg - beg;
714 size = (int) (ovlp_end - ovlp_beg);
716 assert(size <= blk_size);
727 Block* File::PrepareBlockRequest(
int i,
IO *io,
void *req_id,
bool prefetch)
735 const long long off = i * m_block_size;
736 const int last_block = m_num_blocks - 1;
737 const bool cs_net = cache()->RefConfiguration().is_cschk_net();
739 int blk_size, req_size;
740 if (i == last_block) {
741 blk_size = req_size = m_file_size - off;
742 if (cs_net && req_size & 0xFFF) req_size = (req_size & ~0xFFF) + 0x1000;
744 blk_size = req_size = m_block_size;
748 char *buf = cache()->RequestRAM(req_size);
752 b =
new (std::nothrow)
Block(
this, io, req_id, buf, off, blk_size, req_size, prefetch, cs_net);
760 if (m_prefetch_state == kOn && (
int) m_block_map.size() >= m_prefetch_max_blocks_in_flight)
762 m_prefetch_state = kHold;
763 cache()->DeRegisterPrefetchFile(
this);
768 TRACEF(Dump,
"PrepareBlockRequest() " << i <<
" prefetch " << prefetch <<
", allocation failed.");
775 void File::ProcessBlockRequest(
Block *b)
783 snprintf(buf, 256,
"idx=%lld, block=%p, prefetch=%d, off=%lld, req_size=%d, buff=%p, resp_handler=%p ",
784 b->
get_offset()/m_block_size, (
void*)b, b->m_prefetch, b->get_offset(), b->get_req_size(), (
void*)b->get_buff(), (
void*)brh);
785 TRACEF(Dump,
"ProcessBlockRequest() " << buf);
801 for (
BlockList_i bi = blks.begin(); bi != blks.end(); ++bi)
803 ProcessBlockRequest(*bi);
809 void File::RequestBlocksDirect(
IO *io,
ReadRequest *read_req, std::vector<XrdOucIOVec>& ioVec,
int expected_size)
811 int n_chunks = ioVec.size();
814 TRACEF(DumpXL,
"RequestBlocksDirect() issuing ReadV for n_chunks = " << n_chunks <<
815 ", total_size = " << expected_size <<
", n_vec_reads = " << n_vec_reads);
825 io->
GetInput()->
ReadV( *handler, ioVec.data() + pos, n_chunks);
830 int File::ReadBlocksFromDisk(std::vector<XrdOucIOVec>& ioVec,
int expected_size)
832 TRACEF(DumpXL,
"ReadBlocksFromDisk() issuing ReadV for n_chunks = " << (
int) ioVec.size() <<
", total_size = " << expected_size);
834 long long rs = m_data_file->
ReadV(ioVec.data(), (
int) ioVec.size());
838 TRACEF(
Error,
"ReadBlocksFromDisk neg retval = " << rs);
842 if (rs != expected_size)
844 TRACEF(
Error,
"ReadBlocksFromDisk incomplete size = " << rs);
863 if (m_in_shutdown || io->m_in_detach)
866 return m_in_shutdown ? -ENOENT : -EBADF;
874 int ret = m_data_file->
Read(iUserBuff, iUserOff, iUserSize);
883 XrdOucIOVec readV( { iUserOff, iUserSize, 0, iUserBuff } );
885 return ReadOpusCoalescere(io, &readV, 1, rh,
"Read() ");
892 TRACEF(Dump,
"ReadV() for " << readVnum <<
" chunks.");
896 if (m_in_shutdown || io->m_in_detach)
899 return m_in_shutdown ? -ENOENT : -EBADF;
916 return ReadOpusCoalescere(io, readV, readVnum, rh,
"ReadV() ");
921 int File::ReadOpusCoalescere(
IO *io,
const XrdOucIOVec *readV,
int readVnum,
933 int prefetch_cnt = 0;
938 std::unordered_map<Block*, std::vector<ChunkRequest>> blks_ready;
940 std::vector<XrdOucIOVec> iovec_disk;
941 std::vector<XrdOucIOVec> iovec_direct;
942 int iovec_disk_total = 0;
943 int iovec_direct_total = 0;
945 for (
int iov_idx = 0; iov_idx < readVnum; ++iov_idx)
952 const int idx_first = iUserOff / m_block_size;
953 const int idx_last = (iUserOff + iUserSize - 1) / m_block_size;
955 TRACEF(DumpXL, tpfx <<
"sid: " <<
Xrd::hex1 << rh->
m_seq_id <<
" idx_first: " << idx_first <<
" idx_last: " << idx_last);
957 enum LastBlock_e { LB_other, LB_disk, LB_direct };
959 LastBlock_e lbe = LB_other;
961 for (
int block_idx = idx_first; block_idx <= idx_last; ++block_idx)
964 BlockMap_i bi = m_block_map.find(block_idx);
968 long long blk_off = 0;
971 overlap(block_idx, m_block_size, iUserOff, iUserSize, off, blk_off, size);
974 if (bi != m_block_map.end())
976 inc_ref_count(bi->second);
977 TRACEF(Dump, tpfx << (
void*) iUserBuff <<
" inc_ref_count for existing block " << bi->second <<
" idx = " << block_idx);
979 if (bi->second->is_finished())
983 assert(bi->second->is_ok());
985 blks_ready[bi->second].emplace_back(
ChunkRequest(
nullptr, iUserBuff + off, blk_off, size) );
987 if (bi->second->m_prefetch)
998 bi->second->m_chunk_reqs.emplace_back(
ChunkRequest(read_req, iUserBuff + off, blk_off, size) );
1007 TRACEF(DumpXL, tpfx <<
"read from disk " << (
void*)iUserBuff <<
" idx = " << block_idx);
1010 iovec_disk.back().size += size;
1012 iovec_disk.push_back( { block_idx * m_block_size + blk_off, size, 0, iUserBuff + off } );
1013 iovec_disk_total += size;
1027 Block *b = PrepareBlockRequest(block_idx, io, read_req,
false);
1030 TRACEF(Dump, tpfx <<
"inc_ref_count new " << (
void*)iUserBuff <<
" idx = " << block_idx);
1032 blks_to_request.push_back(b);
1041 TRACEF(DumpXL, tpfx <<
"direct block " << block_idx <<
", blk_off " << blk_off <<
", size " << size);
1043 iovec_direct_total += size;
1050 iovec_direct.back().size += size;
1052 long long in_offset = block_idx * m_block_size + blk_off;
1053 char *out_pos = iUserBuff + off;
1060 iovec_direct.push_back( { in_offset, size, 0, out_pos } );
1069 inc_prefetch_hit_cnt(prefetch_cnt);
1074 if ( ! blks_to_request.empty())
1076 ProcessBlockRequests(blks_to_request);
1077 blks_to_request.clear();
1081 if ( ! iovec_direct.empty())
1083 RequestBlocksDirect(io, read_req, iovec_direct, iovec_direct_total);
1085 TRACEF(Dump, tpfx <<
"direct read requests sent out, n_chunks = " << (
int) iovec_direct.size() <<
", total_size = " << iovec_direct_total);
1090 long long bytes_read = 0;
1094 if ( ! blks_ready.empty())
1096 for (
auto &bvi : blks_ready)
1098 for (
auto &cr : bvi.second)
1100 TRACEF(DumpXL, tpfx <<
"ub=" << (
void*)cr.m_buf <<
" from pre-finished block " << bvi.first->m_offset/m_block_size <<
" size " << cr.m_size);
1101 memcpy(cr.m_buf, bvi.first->m_buff + cr.m_off, cr.m_size);
1102 bytes_read += cr.m_size;
1108 if ( ! iovec_disk.empty())
1110 int rc = ReadBlocksFromDisk(iovec_disk, iovec_disk_total);
1111 TRACEF(DumpXL, tpfx <<
"from disk finished size = " << rc);
1126 m_state_cond.
Lock();
1128 for (
auto &bvi : blks_ready)
1129 dec_ref_count(bvi.first, (
int) bvi.second.size());
1143 check_delta_stats();
1159 check_delta_stats();
1164 return error_cond ? error_cond : bytes_read;
1176 long long offset = b->
m_offset - m_offset;
1191 TRACEF(
Error,
"WriteToDisk() write error " << retval);
1193 TRACEF(
Error,
"WriteToDisk() incomplete block write ret=" << retval <<
" (should be " << size <<
")");
1203 const int blk_idx = (b->
m_offset - m_offset) / m_block_size;
1206 TRACEF(Dump,
"WriteToDisk() success set bit for block " << b->
m_offset <<
" size=" << size);
1208 bool schedule_sync =
false;
1227 m_writes_during_sync.push_back(blk_idx);
1232 ++m_non_flushed_cnt;
1236 schedule_sync =
true;
1238 m_non_flushed_cnt = 0;
1244 if (!schedule_sync) {
1251 cache()->ScheduleFileSync(
this);
1263 int ret = m_data_file->
Fsync();
1264 bool errorp =
false;
1270 report_and_merge_delta_stats();
1271 loc_stats = m_stats;
1274 m_cfi.
Write(m_info_file, m_filename.c_str());
1275 int cret = m_info_file->
Fsync();
1278 TRACEF(
Error,
"Sync cinfo file sync error " << cret);
1284 TRACEF(
Error,
"Sync data file sync error " << ret <<
", cinfo file has not been updated");
1290 TRACEF(
Error,
"Sync failed, unlinking local files and initiating shutdown of File object");
1297 m_writes_during_sync.clear();
1303 int written_while_in_sync;
1304 bool resync =
false;
1307 for (std::vector<int>::iterator i = m_writes_during_sync.begin(); i != m_writes_during_sync.end(); ++i)
1311 written_while_in_sync = m_non_flushed_cnt = (int) m_writes_during_sync.size();
1312 m_writes_during_sync.clear();
1316 if (written_while_in_sync > 0 && m_cfi.
IsComplete() && ! m_in_shutdown)
1321 TRACEF(Dump,
"Sync "<< written_while_in_sync <<
" blocks written during sync." << (resync ?
" File is now complete - resyncing." :
""));
1332 void File::free_block(
Block* b)
1335 int i = b->
m_offset / m_block_size;
1336 TRACEF(Dump,
"free_block block " << b <<
" idx = " << i);
1337 size_t ret = m_block_map.erase(i);
1341 TRACEF(
Error,
"free_block did not erase " << i <<
" from map");
1349 if (m_prefetch_state == kHold && (
int) m_block_map.size() < m_prefetch_max_blocks_in_flight)
1351 m_prefetch_state = kOn;
1352 cache()->RegisterPrefetchFile(
this);
1358 bool File::select_current_io_or_disable_prefetching(
bool skip_current)
1362 int io_size = (int) m_io_set.size();
1367 io_ok = (*m_io_set.begin())->m_allow_prefetching;
1370 m_current_io = m_io_set.begin();
1373 else if (io_size > 1)
1375 IoSet_i mi = m_current_io;
1376 if (skip_current && mi != m_io_set.end()) ++mi;
1378 for (
int i = 0; i < io_size; ++i)
1380 if (mi == m_io_set.end()) mi = m_io_set.begin();
1382 if ((*mi)->m_allow_prefetching)
1394 m_current_io = m_io_set.end();
1395 m_prefetch_state = kStopped;
1396 cache()->DeRegisterPrefetchFile(
this);
1404 void File::ProcessDirectReadFinished(
ReadRequest *rreq,
int bytes_read,
int error_cond)
1410 TRACEF(
Error,
"Read(), direct read finished with error " << -error_cond <<
" " <<
XrdSysE2T(-error_cond));
1412 m_state_cond.
Lock();
1428 FinalizeReadRequest(rreq);
1455 TRACEF(Dump,
"ProcessBlockSuccess() ub=" << (
void*)creq.
m_buf <<
" from finished block " << b->
m_offset/m_block_size <<
" size " << creq.
m_size);
1458 m_state_cond.
Lock();
1463 rreq->m_stats.m_BytesMissed += creq.
m_size;
1465 rreq->m_stats.m_BytesHit += creq.
m_size;
1467 --rreq->m_n_chunk_reqs;
1470 inc_prefetch_hit_cnt(1);
1474 bool rreq_complete = rreq->is_complete();
1479 FinalizeReadRequest(rreq);
1489 check_delta_stats();
1496 void File::ProcessBlockResponse(
Block *b,
int res)
1498 static const char* tpfx =
"ProcessBlockResponse ";
1500 TRACEF(Dump, tpfx <<
"block=" << b <<
", idx=" << b->
m_offset/m_block_size <<
", off=" << b->
m_offset <<
", res=" << res);
1502 if (res >= 0 && res != b->
get_size())
1506 TRACEF(
Error, tpfx <<
"Wrong number of bytes received, assuming remote/local file size mismatch, unlinking local files and initiating shutdown of File object");
1510 m_state_cond.
Lock();
1516 IoSet_i mi = m_io_set.find(io);
1517 if (mi != m_io_set.end())
1519 --io->m_active_prefetches;
1522 if (res < 0 && io->m_allow_prefetching)
1524 TRACEF(
Debug, tpfx <<
"after failed prefetch on io " << io <<
" disabling prefetching on this io.");
1525 io->m_allow_prefetching =
false;
1528 if (m_prefetch_state == kOn || m_prefetch_state == kHold)
1530 if ( ! select_current_io_or_disable_prefetching(
false) )
1532 TRACEF(
Debug, tpfx <<
"stopping prefetching after io " << b->
get_io() <<
" marked as bad.");
1538 if (b->
m_refcnt == 0 && (res < 0 || m_in_shutdown))
1555 TRACEF(Dump, tpfx <<
"inc_ref_count idx=" << b->
m_offset/m_block_size);
1556 if ( ! m_in_shutdown)
1562 cache()->AddWriteTask(b,
true);
1571 for (
auto &creq : creqs_to_notify)
1573 ProcessBlockSuccess(b, creq);
1582 <<
", io=" << b->
get_io() <<
", error=" << res);
1587 <<
", io=" << b->
get_io() <<
" incomplete, got " << res <<
" expected " << b->
get_size());
1588 #if defined(__APPLE__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) || defined(__FreeBSD__)
1599 std::list<ReadRequest*> rreqs_to_complete;
1608 ProcessBlockError(b, rreq);
1611 rreqs_to_complete.push_back(rreq);
1616 creqs_to_keep.push_back(creq);
1620 bool reissue =
false;
1621 if ( ! creqs_to_keep.empty())
1623 ReadRequest *rreq = creqs_to_keep.front().m_read_req;
1625 TRACEF(
Debug,
"ProcessBlockResponse() requested block " << (
void*)b <<
" failed with another io " <<
1626 b->
get_io() <<
" - reissuing request with my io " << rreq->
m_io);
1635 for (
auto rreq : rreqs_to_complete)
1636 FinalizeReadRequest(rreq);
1639 ProcessBlockRequest(b);
1647 return m_filename.c_str();
1652 int File::offsetIdx(
int iIdx)
const
1654 return iIdx - m_offset/m_block_size;
1668 TRACEF(DumpXL,
"Prefetch() entering.");
1672 if (m_prefetch_state != kOn)
1677 if ( ! select_current_io_or_disable_prefetching(
true) )
1679 TRACEF(
Error,
"Prefetch no available IO object found, prefetching stopped. This should not happen, i.e., prefetching should be stopped before.");
1684 for (
int f = 0; f < m_num_blocks; ++f)
1688 int f_act = f + m_offset / m_block_size;
1690 BlockMap_i bi = m_block_map.find(f_act);
1691 if (bi == m_block_map.end())
1693 Block *b = PrepareBlockRequest(f_act, *m_current_io,
nullptr,
true);
1696 TRACEF(Dump,
"Prefetch take block " << f_act);
1700 inc_prefetch_read_cnt(1);
1705 TRACEF(
Warning,
"Prefetch allocation failed for block " << f_act);
1714 TRACEF(
Debug,
"Prefetch file is complete, stopping prefetch.");
1715 m_prefetch_state = kComplete;
1716 cache()->DeRegisterPrefetchFile(
this);
1720 (*m_current_io)->m_active_prefetches += (int) blks.size();
1724 if ( ! blks.empty())
1726 ProcessBlockRequests(blks);
1735 return m_prefetch_score;
1748 void File::insert_remote_location(
const std::string &loc)
1752 size_t p = loc.find_first_of(
'@');
1753 m_remote_locations.insert(&loc[p != std::string::npos ? p + 1 : 0]);
1760 if ( ! m_remote_locations.empty())
1764 for (std::set<std::string>::iterator i = m_remote_locations.begin(); i != m_remote_locations.end(); ++i, ++nl)
1768 s.reserve(2 + sl + 2*nl + nl - 1 + 1);
1771 for (std::set<std::string>::iterator i = m_remote_locations.begin(); i != m_remote_locations.end(); ++i, ++j)
1773 s +=
'"'; s += *i; s +=
'"';
1774 if (j < nl) s +=
',';
#define ERRNO_AND_ERRSTR(err_code)
#define TRACEF_INT(act, x)
const char * XrdSysE2T(int errcode)
virtual int Ftruncate(unsigned long long flen)
virtual int Fstat(struct stat *buf)
virtual int Close(long long *retsz=0)=0
virtual int Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv &env)
virtual ssize_t Read(off_t offset, size_t size)
virtual ssize_t pgWrite(void *buffer, off_t offset, size_t wrlen, uint32_t *csvec, uint64_t opts)
virtual ssize_t ReadV(XrdOucIOVec *readV, int rdvcnt)
virtual ssize_t Write(const void *buffer, off_t offset, size_t size)
virtual int Create(const char *tid, const char *path, mode_t mode, XrdOucEnv &env, int opts=0)=0
virtual XrdOssDF * newFile(const char *tident)=0
virtual int Stat(const char *path, struct stat *buff, int opts=0, XrdOucEnv *envP=0)=0
virtual int Unlink(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
virtual void Done(int result)=0
virtual const char * Path()=0
virtual int pgRead(char *buff, long long offs, int rdlen, std::vector< uint32_t > &csvec, uint64_t opts=0, int *csfix=0)
virtual int ReadV(const XrdOucIOVec *readV, int rnum)
void Put(const char *varname, const char *value)
void Done(int result) override
int * ptr_n_cksum_errors()
void * get_req_id() const
long long get_offset() const
vChunkRequest_t m_chunk_reqs
vCkSum_t & ref_cksum_vec()
bool req_cksum_net() const
void reset_error_and_set_io(IO *io, void *rid)
Attaches/creates and detaches/deletes cache-io objects for disk based cache.
bool blocksize_str2value(const char *from, const char *str, long long &val, long long min, long long max) const
const Configuration & RefConfiguration() const
Reference XrdPfc configuration.
static ResourceMonitor & ResMon()
static Cache & GetInstance()
Singleton access.
XrdSysTrace * GetTrace() const
int UnlinkFile(const std::string &f_name, bool fail_if_open)
Remove cinfo and data files from cache.
static const Cache & TheOne()
XrdSysError * GetLog() const
void Done(int result) override
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
std::string GetRemoteLocations() const
int Fstat(struct stat &sbuff)
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.
void BlocksRemovedFromWriteQ(std::list< Block * > &)
Handle removal of a set of blocks from Cache's write queue.
friend class DirectResponseHandler
void Sync()
Sync file cache inf o and output data with disk.
XrdSysTrace * GetTrace() const
int Read(IO *io, char *buff, long long offset, int size, ReadReqRH *rh)
Normal read.
void ioUpdated(IO *io)
Notification from IO that it has been updated (remote open).
long long initiate_emergency_shutdown()
void BlockRemovedFromWriteQ(Block *)
Handle removal of a block from Cache's write queue.
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.
bool register_incomplete_read()
XrdOucCacheIO * GetInput()
bool register_block_error(int res)
RAtomic_int m_active_read_reqs
number of active read requests
const char * GetLocation()
Status of cached file. Can be read from and written into a binary file.
void SetBitPrefetch(int i)
Mark block as obtained through prefetch.
static const char * s_infoExtension
void SetBitSynced(int i)
Mark block as synced to disk.
time_t GetNoCkSumTimeForUVKeep() const
CkSumCheck_e GetCkSumState() const
void WriteIOStatAttach()
Write open time in the last entry of access statistics.
bool Write(XrdOssDF *fp, const char *dname, const char *fname=0)
void DowngradeCkSumState(CkSumCheck_e css_ref)
void ResetAllAccessStats()
Reset IO Stats.
bool TestBitPrefetch(int i) const
Test if block at the given index has been prefetched.
bool IsComplete() const
Get complete status.
bool IsCkSumCache() const
void SetBitWritten(int i)
Mark block as written to disk.
long long GetBufferSize() const
Get prefetch buffer size.
void WriteIOStat(Stats &s)
Write bytes missed, hits, and disk.
long long GetExpectedDataFileSize() const
Get expected data file size.
bool TestBitWritten(int i) const
Test if block at the given index is written to disk.
bool Read(XrdOssDF *fp, const char *dname, const char *fname=0)
Read content of cinfo file into this object.
void SetCkSumState(CkSumCheck_e css)
void SetBufferSizeFileSizeAndCreationTime(long long bs, long long fs)
void WriteIOStatDetach(Stats &s)
Write close time together with bytes missed, hits, and disk.
int GetNBlocks() const
Get number of blocks represented in download-state bit-vector.
void CrossCheckIfScanIsInProgress(const std::string &lfn, XrdSysCondVar &cond)
int register_file_open(const std::string &filename, time_t open_timestamp, bool existing_file)
void register_file_purge(DirState *target, long long size_in_st_blocks)
void register_file_update_stats(int token_id, const Stats &stats)
void register_file_close(int token_id, time_t close_timestamp, const Stats &full_stats)
Statistics of cache utilisation by a File object.
void AddReadStats(const Stats &s)
long long m_StBlocksAdded
number of 512-byte blocks the file has grown by
long long m_BytesBypassed
number of bytes served directly through XrdCl
void AddUp(const Stats &s)
void AddWriteStats(long long bytes_written, int n_cks_errs)
long long BytesReadAndWritten() const
void AddBytesHit(long long bh)
long long m_BytesHit
number of bytes served from disk
long long m_BytesWritten
number of bytes written to disk
void IoDetach(int duration)
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.
std::vector< ChunkRequest > vChunkRequest_t
constexpr int kReadPending
std::list< Block * > BlockList_t
std::list< Block * >::iterator BlockList_i
static const int maxRVdsz
static const int maxRvecsz
Contains parameters configurable from the xrootd config file.
long long m_flushCnt
nuber of unsynced blcoks on disk before flush is called
long long m_cgi_max_bufferSize
max buffer size allowed in pfc.blocksize
int m_cgi_min_prefetch_max_blocks
min prefetch block count allowed in pfc.prefetch
bool does_cschk_have_missing_bits(CkSumCheck_e cks_on_file) const
bool m_cgi_prefetch_allowed
allow cgi setting of prefetch
CkSumCheck_e get_cs_Chk() const
int m_prefetch_max_blocks
default maximum number of blocks to prefetch per file
bool should_uvkeep_purge(time_t delta) const
std::string m_data_space
oss space for data files
long long m_bufferSize
cache block size, default 128 kB
long long m_cgi_min_bufferSize
min buffer size allowed in pfc.blocksize
std::string m_meta_space
oss space for metadata files (cinfo)
int m_cgi_max_prefetch_max_blocks
max prefetch block count allowed in pfc.prefetch
std::string m_username
username passed to oss plugin
bool m_cgi_blocksize_allowed
allow cgi setting of blocksize
void update_error_cond(int ec)