XRootD
Loading...
Searching...
No Matches
XrdPfc.cc
Go to the documentation of this file.
1//----------------------------------------------------------------------------------
2// Copyright (c) 2014 by Board of Trustees of the Leland Stanford, Jr., University
3// Author: Alja Mrak-Tadel, Matevz Tadel, Brian Bockelman
4//----------------------------------------------------------------------------------
5// XRootD is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// XRootD is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
17//----------------------------------------------------------------------------------
18
19#include <fcntl.h>
20#include <sstream>
21#include <algorithm>
22#include <sys/statvfs.h>
23
24#include "XrdCl/XrdClURL.hh"
27
28#include "XrdOuc/XrdOucEnv.hh"
29#include "XrdOuc/XrdOucUtils.hh"
31#include "XrdOuc/XrdOucJson.hh"
32
33#include "XrdSys/XrdSysTimer.hh"
34#include "XrdSys/XrdSysTrace.hh"
35#include "XrdSys/XrdSysXAttr.hh"
36
38
39#include "XrdOss/XrdOss.hh"
41
42#include "XrdPfc.hh"
43#include "XrdPfcTrace.hh"
44#include "XrdPfcFSctl.hh"
45#include "XrdPfcInfo.hh"
46#include "XrdPfcIOFile.hh"
47#include "XrdPfcIOFileBlock.hh"
49
51
52using namespace XrdPfc;
53
54Cache *Cache::m_instance = nullptr;
56
57
59{
61 return 0;
62}
63
65{
67 return 0;
68}
69
70void *PrefetchThread(void*)
71{
73 return 0;
74}
75
76//==============================================================================
77
78extern "C"
79{
81 const char *config_filename,
82 const char *parameters,
83 XrdOucEnv *env)
84{
85 XrdSysError err(logger, "");
86 err.Say("++++++ Proxy file cache initialization started.");
87
88 if ( ! env ||
89 ! (XrdPfc::Cache::schedP = (XrdScheduler*) env->GetPtr("XrdScheduler*")))
90 {
93 }
94
95 Cache &instance = Cache::CreateInstance(logger, env);
96
97 if (! instance.Config(config_filename, parameters, env))
98 {
99 err.Say("Config Proxy file cache initialization failed.");
100 return 0;
101 }
102 err.Say("++++++ Proxy file cache initialization completed.");
103
104 {
105 pthread_t tid;
106
107 XrdSysThread::Run(&tid, ResourceMonitorThread, 0, 0, "XrdPfc ResourceMonitor");
108
109 for (int wti = 0; wti < instance.RefConfiguration().m_wqueue_threads; ++wti)
110 {
111 XrdSysThread::Run(&tid, ProcessWriteTaskThread, 0, 0, "XrdPfc WriteTasks ");
112 }
113
114 if (instance.is_prefetch_enabled())
115 {
116 XrdSysThread::Run(&tid, PrefetchThread, 0, 0, "XrdPfc Prefetch ");
117 }
118 }
119
120 XrdPfcFSctl* pfcFSctl = new XrdPfcFSctl(instance, logger);
121 env->PutPtr("XrdFSCtl_PC*", pfcFSctl);
122
123 return &instance;
124}
125}
126
127//==============================================================================
128
130{
131 assert (m_instance == 0);
132 m_instance = new Cache(logger, env);
133 return *m_instance;
134}
135
136 Cache& Cache::GetInstance() { return *m_instance; }
137const Cache& Cache::TheOne() { return *m_instance; }
138const Configuration& Cache::Conf() { return m_instance->RefConfiguration(); }
139 ResourceMonitor& Cache::ResMon() { return m_instance->RefResMon(); }
140
142{
143 if (! m_decisionpoints.empty())
144 {
145 XrdCl::URL url(io->Path());
146 std::string filename = url.GetPath();
147 std::vector<Decision*>::const_iterator it;
148 for (it = m_decisionpoints.begin(); it != m_decisionpoints.end(); ++it)
149 {
150 XrdPfc::Decision *d = *it;
151 if (! d) continue;
152 if (! d->Decide(filename, *m_oss))
153 {
154 return false;
155 }
156 }
157 }
158
159 return true;
160}
161
163 XrdOucCache("pfc"),
164 m_env(env),
165 m_log(logger, "XrdPfc_"),
166 m_trace(new XrdSysTrace("XrdPfc", logger)),
167 m_traceID("Cache"),
168 m_oss(0),
169 m_gstream(0),
170 m_purge_pin(0),
171 m_prefetch_condVar(0),
172 m_prefetch_enabled(false),
173 m_RAM_used(0),
174 m_RAM_write_queue(0),
175 m_RAM_std_size(0),
176 m_isClient(false),
177 m_active_cond(0)
178{
179 // Default log level is Warning.
180 m_trace->What = 2;
181}
182
184{
185 const char* tpfx = "Attach() ";
186
187 if (Options & XrdOucCache::optRW)
188 {
189 TRACE(Info, tpfx << "passing through write operation" << obfuscateAuth(io->Path()));
190 }
191 else if (Cache::GetInstance().Decide(io))
192 {
193 TRACE(Info, tpfx << obfuscateAuth(io->Path()));
194
195 IO *cio;
196
197 if (Cache::GetInstance().RefConfiguration().m_hdfsmode)
198 {
199 cio = new IOFileBlock(io, *this);
200 }
201 else
202 {
203 IOFile *iof = new IOFile(io, *this);
204
205 if ( ! iof->HasFile())
206 {
207 delete iof;
208 // TODO - redirect instead. But this is kind of an awkward place for it.
209 // errno is set during IOFile construction.
210 TRACE(Error, tpfx << "Failed opening local file, falling back to remote access " << io->Path());
211 return io;
212 }
213
214 cio = iof;
215 }
216
217 TRACE_PC(Debug, const char* loc = io->Location(), tpfx << io->Path() << " location: " <<
218 ((loc && loc[0] != 0) ? loc : "<deferred open>"));
219
220 return cio;
221 }
222 else
223 {
224 TRACE(Info, tpfx << "decision decline " << io->Path());
225 }
226 return io;
227}
228
229void Cache::AddWriteTask(Block* b, bool fromRead)
230{
231 TRACE(Dump, "AddWriteTask() offset=" << b->m_offset << ". file " << b->get_file()->GetLocalPath());
232
233 {
234 XrdSysMutexHelper lock(&m_RAM_mutex);
235 m_RAM_write_queue += b->get_size();
236 }
237
238 m_writeQ.condVar.Lock();
239 if (fromRead)
240 m_writeQ.queue.push_back(b);
241 else
242 m_writeQ.queue.push_front(b);
243 m_writeQ.size++;
244 m_writeQ.condVar.Signal();
245 m_writeQ.condVar.UnLock();
246}
247
249{
250 std::list<Block*> removed_blocks;
251 long long sum_size = 0;
252
253 m_writeQ.condVar.Lock();
254 std::list<Block*>::iterator i = m_writeQ.queue.begin();
255 while (i != m_writeQ.queue.end())
256 {
257 if ((*i)->m_file == file)
258 {
259 TRACE(Dump, "Remove entries for " << (void*)(*i) << " path " << file->lPath());
260 std::list<Block*>::iterator j = i++;
261 removed_blocks.push_back(*j);
262 sum_size += (*j)->get_size();
263 m_writeQ.queue.erase(j);
264 --m_writeQ.size;
265 }
266 else
267 {
268 ++i;
269 }
270 }
271 m_writeQ.condVar.UnLock();
272
273 {
274 XrdSysMutexHelper lock(&m_RAM_mutex);
275 m_RAM_write_queue -= sum_size;
276 }
277
278 file->BlocksRemovedFromWriteQ(removed_blocks);
279}
280
282{
283 std::vector<Block*> blks_to_write(m_configuration.m_wqueue_blocks);
284
285 while (true)
286 {
287 m_writeQ.condVar.Lock();
288 while (m_writeQ.size == 0)
289 {
290 m_writeQ.condVar.Wait();
291 }
292
293 // MT -- optimize to pop several blocks if they are available (or swap the list).
294 // This makes sense especially for smallish block sizes.
295
296 int n_pushed = std::min(m_writeQ.size, m_configuration.m_wqueue_blocks);
297 long long sum_size = 0;
298
299 for (int bi = 0; bi < n_pushed; ++bi)
300 {
301 Block* block = m_writeQ.queue.front();
302 m_writeQ.queue.pop_front();
303 m_writeQ.writes_between_purges += block->get_size();
304 sum_size += block->get_size();
305
306 blks_to_write[bi] = block;
307
308 TRACE(Dump, "ProcessWriteTasks for block " << (void*)(block) << " path " << block->m_file->lPath());
309 }
310 m_writeQ.size -= n_pushed;
311
312 m_writeQ.condVar.UnLock();
313
314 {
315 XrdSysMutexHelper lock(&m_RAM_mutex);
316 m_RAM_write_queue -= sum_size;
317 }
318
319 for (int bi = 0; bi < n_pushed; ++bi)
320 {
321 Block* block = blks_to_write[bi];
322
323 block->m_file->WriteBlockToDisk(block);
324 }
325 }
326}
327
329{
330 // Called from ResourceMonitor for an alternative estimation of disk writes.
331 XrdSysCondVarHelper lock(&m_writeQ.condVar);
332 long long ret = m_writeQ.writes_between_purges;
333 m_writeQ.writes_between_purges = 0;
334 return ret;
335}
336
337//==============================================================================
338
339char* Cache::RequestRAM(long long size)
340{
341 static const size_t s_block_align = sysconf(_SC_PAGESIZE);
342
343 bool std_size = (size == m_configuration.m_bufferSize);
344
345 m_RAM_mutex.Lock();
346
347 long long total = m_RAM_used + size;
348
349 if (total <= m_configuration.m_RamAbsAvailable)
350 {
351 m_RAM_used = total;
352 if (std_size && m_RAM_std_size > 0)
353 {
354 char *buf = m_RAM_std_blocks.back();
355 m_RAM_std_blocks.pop_back();
356 --m_RAM_std_size;
357
358 m_RAM_mutex.UnLock();
359
360 return buf;
361 }
362 else
363 {
364 m_RAM_mutex.UnLock();
365 char *buf;
366 if (posix_memalign((void**) &buf, s_block_align, (size_t) size))
367 {
368 // Report out of mem? Probably should report it at least the first time,
369 // then periodically.
370 return 0;
371 }
372 return buf;
373 }
374 }
375 m_RAM_mutex.UnLock();
376 return 0;
377}
378
379void Cache::ReleaseRAM(char* buf, long long size)
380{
381 bool std_size = (size == m_configuration.m_bufferSize);
382 {
383 XrdSysMutexHelper lock(&m_RAM_mutex);
384
385 m_RAM_used -= size;
386
387 if (std_size && m_RAM_std_size < m_configuration.m_RamKeepStdBlocks)
388 {
389 m_RAM_std_blocks.push_back(buf);
390 ++m_RAM_std_size;
391 return;
392 }
393 }
394 free(buf);
395}
396
397File* Cache::GetFile(const std::string& path, IO* io, long long off, long long filesize)
398{
399 // Called from virtual IOFile constructor.
400
401 TRACE(Debug, "GetFile " << path << ", io " << io);
402
403 ActiveMap_i it;
404
405 {
406 XrdSysCondVarHelper lock(&m_active_cond);
407
408 while (true)
409 {
410 it = m_active.find(path);
411
412 // File is not open or being opened. Mark it as being opened and
413 // proceed to opening it outside of while loop.
414 if (it == m_active.end())
415 {
416 it = m_active.insert(std::make_pair(path, (File*) 0)).first;
417 break;
418 }
419
420 if (it->second != 0)
421 {
422 it->second->AddIO(io);
423 inc_ref_cnt(it->second, false, true);
424
425 return it->second;
426 }
427 else
428 {
429 // Wait for some change in m_active, then recheck.
430 m_active_cond.Wait();
431 }
432 }
433 }
434
435 // This is always true, now that IOFileBlock is unsupported.
436
437 if (filesize == 0)
438 {
439 struct stat st;
440 int res = io->Fstat(st);
441 if (res < 0) {
442 errno = res;
443 filesize = -1;
444 TRACE(Error, "GetFile, could not get valid stat");
445 } else if (res > 0) {
446 errno = ENOTSUP;
447 filesize = -1;
448 TRACE(Error, "GetFile, stat returned positive value, this should NOT happen here");
449 } else {
450 filesize = st.st_size;
451 }
452 }
453
454 File *file = 0;
455
456 if (filesize >= 0)
457 {
458 file = File::FileOpen(path, off, filesize, io->GetInput());
459 }
460
461 {
462 XrdSysCondVarHelper lock(&m_active_cond);
463
464 if (file)
465 {
466 inc_ref_cnt(file, false, true);
467 it->second = file;
468
469 file->AddIO(io);
470 }
471 else
472 {
473 m_active.erase(it);
474 }
475
476 m_active_cond.Broadcast();
477 }
478
479 return file;
480}
481
483{
484 // Called from virtual IO::DetachFinalize.
485
486 TRACE(Debug, "ReleaseFile " << f->GetLocalPath() << ", io " << io);
487
488 {
489 XrdSysCondVarHelper lock(&m_active_cond);
490
491 f->RemoveIO(io);
492 }
493 dec_ref_cnt(f, true);
494}
495
496
497namespace
498{
499
500class DiskSyncer : public XrdJob
501{
502private:
503 File *m_file;
504 bool m_high_debug;
505
506public:
507 DiskSyncer(File *f, bool high_debug, const char *desc = "") :
508 XrdJob(desc),
509 m_file(f),
510 m_high_debug(high_debug)
511 {}
512
513 void DoIt()
514 {
515 m_file->Sync();
516 Cache::GetInstance().FileSyncDone(m_file, m_high_debug);
517 delete this;
518 }
519};
520
521
522class CommandExecutor : public XrdJob
523{
524private:
525 std::string m_command_url;
526
527public:
528 CommandExecutor(const std::string& command, const char *desc = "") :
529 XrdJob(desc),
530 m_command_url(command)
531 {}
532
533 void DoIt()
534 {
535 Cache::GetInstance().ExecuteCommandUrl(m_command_url);
536 delete this;
537 }
538};
539
540}
541
542//==============================================================================
543
544void Cache::schedule_file_sync(File* f, bool ref_cnt_already_set, bool high_debug)
545{
546 DiskSyncer* ds = new DiskSyncer(f, high_debug);
547
548 if ( ! ref_cnt_already_set) inc_ref_cnt(f, true, high_debug);
549
550 schedP->Schedule(ds);
551}
552
553void Cache::FileSyncDone(File* f, bool high_debug)
554{
555 dec_ref_cnt(f, high_debug);
556}
557
558void Cache::inc_ref_cnt(File* f, bool lock, bool high_debug)
559{
560 // called from GetFile() or SheduleFileSync();
561
562 int tlvl = high_debug ? TRACE_Debug : TRACE_Dump;
563
564 if (lock) m_active_cond.Lock();
565 int rc = f->inc_ref_cnt();
566 if (lock) m_active_cond.UnLock();
567
568 TRACE_INT(tlvl, "inc_ref_cnt " << f->GetLocalPath() << ", cnt at exit = " << rc);
569}
570
571void Cache::dec_ref_cnt(File* f, bool high_debug)
572{
573 // NOT under active lock.
574 // Called from ReleaseFile(), DiskSync callback and stat-like functions.
575
576 int tlvl = high_debug ? TRACE_Debug : TRACE_Dump;
577 int cnt;
578
579 bool emergency_close = false;
580 {
581 XrdSysCondVarHelper lock(&m_active_cond);
582
583 cnt = f->get_ref_cnt();
584 TRACE_INT(tlvl, "dec_ref_cnt " << f->GetLocalPath() << ", cnt at entry = " << cnt);
585
587 {
588 // In this case file has been already removed from m_active map and
589 // does not need to be synced.
590
591 if (cnt == 1)
592 {
593 TRACE_INT(tlvl, "dec_ref_cnt " << f->GetLocalPath() << " is in shutdown, ref_cnt = " << cnt
594 << " -- closing and deleting File object without further ado");
595 emergency_close = true;
596 }
597 else
598 {
599 TRACE_INT(tlvl, "dec_ref_cnt " << f->GetLocalPath() << " is in shutdown, ref_cnt = " << cnt
600 << " -- waiting");
601 f->dec_ref_cnt();
602 return;
603 }
604 }
605 if (cnt > 1)
606 {
607 f->dec_ref_cnt();
608 return;
609 }
610 }
611 if (emergency_close)
612 {
613 f->Close();
614 delete f;
615 return;
616 }
617
618 if (cnt == 1)
619 {
620 if (f->FinalizeSyncBeforeExit())
621 {
622 // Note, here we "reuse" the existing reference count for the
623 // final sync.
624
625 TRACE(Debug, "dec_ref_cnt " << f->GetLocalPath() << ", scheduling final sync");
626 schedule_file_sync(f, true, true);
627 return;
628 }
629 }
630
631 bool finished_p = false;
632 ActiveMap_i act_it;
633 {
634 XrdSysCondVarHelper lock(&m_active_cond);
635
636 cnt = f->dec_ref_cnt();
637 TRACE_INT(tlvl, "dec_ref_cnt " << f->GetLocalPath() << ", cnt after sync_check and dec_ref_cnt = " << cnt);
638 if (cnt == 0)
639 {
640 act_it = m_active.find(f->GetLocalPath());
641 act_it->second = 0;
642
643 finished_p = true;
644 }
645 }
646 if (finished_p)
647 {
648 f->Close();
649 {
650 XrdSysCondVarHelper lock(&m_active_cond);
651 m_active.erase(act_it);
652 m_active_cond.Broadcast();
653 }
654
655 if (m_gstream)
656 {
657 const Stats &st = f->RefStats();
658 const Info::AStat *as = f->GetLastAccessStats();
659
660 char buf[4096];
661 int len = snprintf(buf, 4096, "{\"event\":\"file_close\","
662 "\"lfn\":\"%s\",\"size\":%lld,\"blk_size\":%d,\"n_blks\":%d,\"n_blks_done\":%d,"
663 "\"access_cnt\":%lu,\"attach_t\":%lld,\"detach_t\":%lld,\"remotes\":%s,"
664 "\"b_hit\":%lld,\"b_miss\":%lld,\"b_bypass\":%lld,"
665 "\"b_todisk\":%lld,\"b_prefetch\":%lld,\"n_cks_errs\":%d}",
666 f->GetLocalPath().c_str(), f->GetFileSize(), f->GetBlockSize(),
668 (unsigned long) f->GetAccessCnt(), (long long) as->AttachTime, (long long) as->DetachTime,
669 f->GetRemoteLocations().c_str(),
670 as->BytesHit, as->BytesMissed, as->BytesBypassed,
672 );
673 bool suc = false;
674 if (len < 4096)
675 {
676 suc = m_gstream->Insert(buf, len + 1);
677 }
678 if ( ! suc)
679 {
680 TRACE(Error, "Failed g-stream insertion of file_close record, len=" << len);
681 }
682 }
683
684 delete f;
685 }
686}
687
688bool Cache::IsFileActiveOrPurgeProtected(const std::string& path) const
689{
690 XrdSysCondVarHelper lock(&m_active_cond);
691
692 return m_active.find(path) != m_active.end() ||
693 m_purge_delay_set.find(path) != m_purge_delay_set.end();
694}
695
697{
698 XrdSysCondVarHelper lock(&m_active_cond);
699 m_purge_delay_set.clear();
700}
701
702//==============================================================================
703//=== PREFETCH
704//==============================================================================
705
707{
708 // Can be called with other locks held.
709
710 if ( ! m_prefetch_enabled)
711 {
712 return;
713 }
714
715 m_prefetch_condVar.Lock();
716 m_prefetchList.push_back(file);
717 m_prefetch_condVar.Signal();
718 m_prefetch_condVar.UnLock();
719}
720
721
723{
724 // Can be called with other locks held.
725
726 if ( ! m_prefetch_enabled)
727 {
728 return;
729 }
730
731 m_prefetch_condVar.Lock();
732 for (PrefetchList::iterator it = m_prefetchList.begin(); it != m_prefetchList.end(); ++it)
733 {
734 if (*it == file)
735 {
736 m_prefetchList.erase(it);
737 break;
738 }
739 }
740 m_prefetch_condVar.UnLock();
741}
742
743
745{
746 m_prefetch_condVar.Lock();
747 while (m_prefetchList.empty())
748 {
749 m_prefetch_condVar.Wait();
750 }
751
752 // std::sort(m_prefetchList.begin(), m_prefetchList.end(), myobject);
753
754 size_t l = m_prefetchList.size();
755 int idx = rand() % l;
756 File* f = m_prefetchList[idx];
757
758 m_prefetch_condVar.UnLock();
759 return f;
760}
761
762
764{
765 const long long limit_RAM = m_configuration.m_RamAbsAvailable * 7 / 10;
766
767 while (true)
768 {
769 m_RAM_mutex.Lock();
770 bool doPrefetch = (m_RAM_used < limit_RAM);
771 m_RAM_mutex.UnLock();
772
773 if (doPrefetch)
774 {
776 f->Prefetch();
777 }
778 else
779 {
781 }
782 }
783}
784
785
786//==============================================================================
787//=== Virtuals from XrdOucCache
788//==============================================================================
789
790//------------------------------------------------------------------------------
804
805int Cache::LocalFilePath(const char *curl, char *buff, int blen,
806 LFP_Reason why, bool forall)
807{
808 static const mode_t groupReadable = S_IRUSR | S_IWUSR | S_IRGRP;
809 static const mode_t worldReadable = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
810 static const char *lfpReason[] = { "ForAccess", "ForInfo", "ForPath" };
811
812 TRACE(Debug, "LocalFilePath '" << curl << "', why=" << lfpReason[why]);
813
814 if (buff && blen > 0) buff[0] = 0;
815
816 XrdCl::URL url(curl);
817 std::string f_name = url.GetPath();
818 std::string i_name = f_name + Info::s_infoExtension;
819
820 if (why == ForPath)
821 {
822 int ret = m_oss->Lfn2Pfn(f_name.c_str(), buff, blen);
823 TRACE(Info, "LocalFilePath '" << curl << "', why=" << lfpReason[why] << " -> " << ret);
824 return ret;
825 }
826
827 {
828 XrdSysCondVarHelper lock(&m_active_cond);
829 m_purge_delay_set.insert(f_name);
830 }
831
832 struct stat sbuff, sbuff2;
833 if (m_oss->Stat(f_name.c_str(), &sbuff) == XrdOssOK &&
834 m_oss->Stat(i_name.c_str(), &sbuff2) == XrdOssOK)
835 {
836 if (S_ISDIR(sbuff.st_mode))
837 {
838 TRACE(Info, "LocalFilePath '" << curl << "', why=" << lfpReason[why] << " -> EISDIR");
839 return -EISDIR;
840 }
841 else
842 {
843 bool read_ok = false;
844 bool is_complete = false;
845
846 // Lock and check if the file is active. If NOT, keep the lock
847 // and add dummy access after successful reading of info file.
848 // If it IS active, just release the lock, this ongoing access will
849 // assure the file continues to exist.
850
851 // XXXX How can I just loop over the cinfo file when active?
852 // Can I not get is_complete from the existing file?
853 // Do I still want to inject access record?
854 // Oh, it writes only if not active .... still let's try to use existing File.
855
856 m_active_cond.Lock();
857
858 bool is_active = m_active.find(f_name) != m_active.end();
859
860 if (is_active) m_active_cond.UnLock();
861
862 XrdOssDF* infoFile = m_oss->newFile(m_configuration.m_username.c_str());
863 XrdOucEnv myEnv;
864 int res = infoFile->Open(i_name.c_str(), O_RDWR, 0600, myEnv);
865 if (res >= 0)
866 {
867 Info info(m_trace, 0);
868 if (info.Read(infoFile, i_name.c_str()))
869 {
870 read_ok = true;
871
872 is_complete = info.IsComplete();
873
874 // Add full-size access if reason is for access.
875 if ( ! is_active && is_complete && why == ForAccess)
876 {
877 info.WriteIOStatSingle(info.GetFileSize());
878 info.Write(infoFile, i_name.c_str());
879 }
880 }
881 infoFile->Close();
882 }
883 delete infoFile;
884
885 if ( ! is_active) m_active_cond.UnLock();
886
887 if (read_ok)
888 {
889 if ((is_complete || why == ForInfo) && buff != 0)
890 {
891 int res2 = m_oss->Lfn2Pfn(f_name.c_str(), buff, blen);
892 if (res2 < 0)
893 return res2;
894
895 // Normally, files are owned by us but when direct cache access
896 // is wanted and possible, make sure the file is world readable.
897 if (why == ForAccess)
898 {mode_t mode = (forall ? worldReadable : groupReadable);
899 if (((sbuff.st_mode & worldReadable) != mode)
900 && (m_oss->Chmod(f_name.c_str(), mode) != XrdOssOK))
901 {is_complete = false;
902 *buff = 0;
903 }
904 }
905 }
906
907 TRACE(Info, "LocalFilePath '" << curl << "', why=" << lfpReason[why] <<
908 (is_complete ? " -> FILE_COMPLETE_IN_CACHE" : " -> EREMOTE"));
909
910 return is_complete ? 0 : -EREMOTE;
911 }
912 }
913 }
914
915 TRACE(Info, "LocalFilePath '" << curl << "', why=" << lfpReason[why] << " -> ENOENT");
916 return -ENOENT;
917}
918
919//______________________________________________________________________________
920// If supported, write Cache-Control as xattr to cinfo file.
921// One can use file descriptor or full path interchangeably
922//------------------------------------------------------------------------------
923void Cache::WriteCacheControlXAttr(int cinfo_fd, const char* path, const std::string& cc)
924{
925 if (m_metaXattr) {
926 int res = XrdSysXAttrActive->Set("pfc.cache-control", cc.c_str(), cc.size(), path, cinfo_fd, 0);
927 if (res != 0) {
928 TRACE(Error, "WritecacheControlXAttr error setting xattr " << res);
929 }
930 }
931}
932
933//______________________________________________________________________________
934// If supported, write file_size as xattr to cinfo file.
935//------------------------------------------------------------------------------
936void Cache::WriteFileSizeXAttr(int cinfo_fd, long long file_size)
937{
938 if (m_metaXattr) {
939 int res = XrdSysXAttrActive->Set("pfc.fsize", &file_size, sizeof(long long), 0, cinfo_fd, 0);
940 if (res != 0) {
941 TRACE(Debug, "WriteFileSizeXAttr error setting xattr " << res);
942 }
943 }
944}
945
946//______________________________________________________________________________
947// Determine full size of the data file from the corresponding cinfo-file name.
948// Attempts to read xattr first and falls back to reading of the cinfo file.
949// Returns -error on failure.
950//------------------------------------------------------------------------------
951long long Cache::DetermineFullFileSize(const std::string &cinfo_fname)
952{
953 if (m_metaXattr) {
954 char pfn[4096];
955 m_oss->Lfn2Pfn(cinfo_fname.c_str(), pfn, 4096);
956 long long fsize = -1ll;
957 int res = XrdSysXAttrActive->Get("pfc.fsize", &fsize, sizeof(long long), pfn);
958 if (res == sizeof(long long))
959 {
960 return fsize;
961 }
962 else
963 {
964 TRACE(Debug, "DetermineFullFileSize error getting xattr " << res);
965 }
966 }
967
968 XrdOssDF *infoFile = m_oss->newFile(m_configuration.m_username.c_str());
969 XrdOucEnv env;
970 long long ret;
971 int res = infoFile->Open(cinfo_fname.c_str(), O_RDONLY, 0600, env);
972 if (res < 0) {
973 ret = res;
974 } else {
975 Info info(m_trace, 0);
976 if ( ! info.Read(infoFile, cinfo_fname.c_str())) {
977 ret = -EBADF;
978 } else {
979 ret = info.GetFileSize();
980 }
981 infoFile->Close();
982 }
983 delete infoFile;
984 return ret;
985}
986
987//______________________________________________________________________________
988// Get cache control attributes from the corresponding cinfo-file name.
989// Returns -error on failure.
990//------------------------------------------------------------------------------
991int Cache::GetCacheControlXAttr(const std::string &cinfo_fname, std::string& ival) const
992{
993 if (m_metaXattr) {
994
995 char pfn[4096];
996 m_oss->Lfn2Pfn(cinfo_fname.c_str(), pfn, 4096);
997
998 char cc[512];
999 int res = XrdSysXAttrActive->Get("pfc.cache-control", &cc, 512, pfn, -1);
1000 if (res > 0)
1001 {
1002 std::string tmp(cc, res);
1003 ival = tmp;
1004 }
1005 return res;
1006 }
1007 return 0;
1008}
1009
1010//______________________________________________________________________________
1011// Get cache control attributes from the corresponding cinfo-file name.
1012// Returns -error on failure.
1013//------------------------------------------------------------------------------
1014int Cache::GetCacheControlXAttr(int fd, std::string& ival) const
1015{
1016 if (m_metaXattr) {
1017 char cc[512];
1018 int res = XrdSysXAttrActive->Get("pfc.cache-control", &cc, 512, nullptr, fd);
1019 if (res > 0)
1020 {
1021 ival = std::string(cc, res);
1022 return res;
1023 }
1024 }
1025 return 0;
1026}
1027
1028//______________________________________________________________________________
1029// Calculate if the file is to be considered cached for the purposes of
1030// only-if-cached and setting of atime of the Stat() calls.
1031// Returns true if the file is to be conidered cached.
1032//------------------------------------------------------------------------------
1033bool Cache::DecideIfConsideredCached(long long file_size, long long bytes_on_disk)
1034{
1035 if (file_size == 0 || bytes_on_disk >= file_size)
1036 return true;
1037
1038 double frac_on_disk = (double) bytes_on_disk / file_size;
1039
1040 if (file_size <= m_configuration.m_onlyIfCachedMinSize)
1041 {
1042 if (frac_on_disk >= m_configuration.m_onlyIfCachedMinFrac)
1043 return true;
1044 }
1045 else
1046 {
1047 if (bytes_on_disk >= m_configuration.m_onlyIfCachedMinSize &&
1048 frac_on_disk >= m_configuration.m_onlyIfCachedMinFrac)
1049 return true;
1050 }
1051 return false;
1052}
1053
1054//______________________________________________________________________________
1055// Check if the file is cached including m_onlyIfCachedMinSize and m_onlyIfCachedMinFrac
1056// pfc configuration parameters. The logic of accessing the Info file is the same
1057// as in Cache::LocalFilePath.
1065//------------------------------------------------------------------------------
1066int Cache::ConsiderCached(const char *curl)
1067{
1068 static const char* tpfx = "ConsiderCached ";
1069
1070 TRACE(Debug, tpfx << curl);
1071
1072 XrdCl::URL url(curl);
1073 std::string f_name = url.GetPath();
1074
1075 File *file = nullptr;
1076 {
1077 XrdSysCondVarHelper lock(&m_active_cond);
1078 auto it = m_active.find(f_name);
1079 if (it != m_active.end()) {
1080 file = it->second;
1081 // If the file-open is in progress, `file` is a nullptr
1082 // so we cannot increase the reference count. For now,
1083 // simply treat it as if the file open doesn't exist instead
1084 // of trying to wait and see if it succeeds.
1085 if (file) {
1086 inc_ref_cnt(file, false, false);
1087 }
1088 }
1089 }
1090 if (file) {
1091 struct stat sbuff;
1092 int res = file->Fstat(sbuff);
1093 dec_ref_cnt(file, false);
1094 if (res)
1095 return res;
1096 // DecideIfConsideredCached() already called in File::Fstat().
1097 return sbuff.st_atime > 0 ? 0 : -EREMOTE;
1098 }
1099
1100 struct stat sbuff;
1101 int res = m_oss->Stat(f_name.c_str(), &sbuff);
1102 if (res != XrdOssOK) {
1103 TRACE(Debug, tpfx << curl << " -> " << res);
1104 return res;
1105 }
1106 if (S_ISDIR(sbuff.st_mode))
1107 {
1108 TRACE(Debug, tpfx << curl << " -> EISDIR");
1109 return -EISDIR;
1110 }
1111
1112 long long file_size = DetermineFullFileSize(f_name + Info::s_infoExtension);
1113 if (file_size < 0) {
1114 TRACE(Debug, tpfx << curl << " -> " << file_size);
1115 return (int) file_size;
1116 }
1117 bool is_cached = DecideIfConsideredCached(file_size, sbuff.st_blocks * 512ll);
1118
1119 return is_cached ? 0 : -EREMOTE;
1120}
1121
1122//______________________________________________________________________________
1130//------------------------------------------------------------------------------
1131
1132int Cache::Prepare(const char *curl, int oflags, mode_t mode)
1133{
1134 XrdCl::URL url(curl);
1135 std::string f_name = url.GetPath();
1136 std::string i_name = f_name + Info::s_infoExtension;
1137
1138 // Do not allow write access.
1139 if ((oflags & O_ACCMODE) != O_RDONLY)
1140 {
1141 if (Cache::GetInstance().RefConfiguration().m_write_through)
1142 {
1143 return 0;
1144 }
1145 TRACE(Warning, "Prepare write access requested on file " << f_name << ". Denying access.");
1146 return -EROFS;
1147 }
1148
1149 // Intercept xrdpfc_command requests.
1150 if (m_configuration.m_allow_xrdpfc_command && strncmp("/xrdpfc_command/", f_name.c_str(), 16) == 0)
1151 {
1152 // Schedule a job to process command request.
1153 {
1154 CommandExecutor *ce = new CommandExecutor(f_name, "CommandExecutor");
1155
1156 schedP->Schedule(ce);
1157 }
1158
1159 return -EAGAIN;
1160 }
1161
1162 {
1163 XrdSysCondVarHelper lock(&m_active_cond);
1164 m_purge_delay_set.insert(f_name);
1165 }
1166
1167 struct stat sbuff;
1168 if (m_oss->Stat(i_name.c_str(), &sbuff) == XrdOssOK &&
1169 m_oss->Stat(f_name.c_str(), &sbuff) == XrdOssOK)
1170 {
1171
1172 if (m_configuration.m_httpcc && !is_http_cache_valid(f_name, i_name, url))
1173 {
1174 TRACE(Info, "Http cache not valid " << f_name);
1175 UnlinkFile(f_name, false);
1176 return 0;
1177 }
1178
1179 TRACE(Dump, "Prepare defer open " << f_name);
1180 return 1;
1181 }
1182 else
1183 {
1184 return 0;
1185 }
1186}
1187
1188//______________________________________________________________________________
1189// virtual method of XrdOucCache.
1194//------------------------------------------------------------------------------
1195
1196int Cache::Stat(const char *curl, struct stat &sbuff)
1197{
1198 const char *tpfx = "Stat ";
1199
1200 XrdCl::URL url(curl);
1201 std::string f_name = url.GetPath();
1202
1203 File *file = nullptr;
1204 {
1205 XrdSysCondVarHelper lock(&m_active_cond);
1206 auto it = m_active.find(f_name);
1207 if (it != m_active.end()) {
1208 file = it->second;
1209 // If `file` is nullptr, the file-open is in progress; instead
1210 // of waiting for the file-open to finish, simply treat it as if
1211 // the file-open doesn't exist.
1212 if (file) {
1213 inc_ref_cnt(file, false, false);
1214 }
1215 }
1216 }
1217 if (file) {
1218 int res = file->Fstat(sbuff);
1219 dec_ref_cnt(file, false);
1220 TRACE(Debug, tpfx << "from active file " << curl << " -> " << res);
1221 return res;
1222 }
1223
1224 int res = m_oss->Stat(f_name.c_str(), &sbuff);
1225 if (res != XrdOssOK) {
1226 TRACE(Debug, tpfx << curl << " -> " << res);
1227 return 1; // res; -- for only-if-cached
1228 }
1229 if (S_ISDIR(sbuff.st_mode))
1230 {
1231 TRACE(Debug, tpfx << curl << " -> EISDIR");
1232 return -EISDIR;
1233 }
1234
1235 long long file_size = DetermineFullFileSize(f_name + Info::s_infoExtension);
1236 if (file_size < 0) {
1237 TRACE(Debug, tpfx << curl << " -> " << file_size);
1238 return 1; // (int) file_size; -- for only-if-cached
1239 }
1240 sbuff.st_size = file_size;
1241 bool is_cached = DecideIfConsideredCached(file_size, sbuff.st_blocks * 512ll);
1242 if ( ! is_cached)
1243 sbuff.st_atime = 0;
1244
1245 TRACE(Debug, tpfx << "from disk " << curl << " -> " << res);
1246
1247 return 0;
1248}
1249
1250//______________________________________________________________________________
1251// virtual method of XrdOucCache.
1255//------------------------------------------------------------------------------
1256
1257int Cache::Unlink(const char *curl)
1258{
1259 XrdCl::URL url(curl);
1260 std::string f_name = url.GetPath();
1261
1262 // printf("Unlink url=%s\n\t fname=%s\n", curl, f_name.c_str());
1263
1264 return UnlinkFile(f_name, false);
1265}
1266
1267int Cache::UnlinkFile(const std::string& f_name, bool fail_if_open)
1268{
1269 static const char* trc_pfx = "UnlinkFile ";
1270 ActiveMap_i it;
1271 File *file = 0;
1272 long long st_blocks_to_purge = 0;
1273 bool file_existed = false;
1274 {
1275 XrdSysCondVarHelper lock(&m_active_cond);
1276
1277 it = m_active.find(f_name);
1278
1279 if (it != m_active.end())
1280 {
1281 if (fail_if_open)
1282 {
1283 TRACE(Info, trc_pfx << f_name << ", file currently open and force not requested - denying request");
1284 return -EBUSY;
1285 }
1286
1287 // Null File* in m_active map means an operation is ongoing, probably
1288 // Attach() with possible File::Open(). Ask for retry.
1289 if (it->second == 0)
1290 {
1291 TRACE(Info, trc_pfx << f_name << ", an operation on this file is ongoing - denying request");
1292 return -EAGAIN;
1293 }
1294
1295 file = it->second;
1296 st_blocks_to_purge = file->initiate_emergency_shutdown();
1297 it->second = 0;
1298 }
1299 else
1300 {
1301 it = m_active.insert(std::make_pair(f_name, (File*) 0)).first;
1302 }
1303 }
1304
1305 if (file) {
1306 file_existed = true;
1308 } else {
1309 struct stat f_stat;
1310 if (m_oss->Stat(f_name.c_str(), &f_stat) == XrdOssOK) {
1311 file_existed = true;
1312 st_blocks_to_purge = f_stat.st_blocks;
1313 }
1314 }
1315
1316 std::string i_name = f_name + Info::s_infoExtension;
1317
1318 // Unlink file & cinfo
1319 int f_ret = m_oss->Unlink(f_name.c_str());
1320 int i_ret = m_oss->Unlink(i_name.c_str());
1321
1322 // Count a removal for any file that existed, even with zero blocks, and never
1323 // for an absent one.
1324 if (file_existed)
1325 m_res_mon->register_file_purge(f_name, st_blocks_to_purge);
1326
1327 TRACE(Debug, trc_pfx << f_name << ", f_ret=" << f_ret << ", i_ret=" << i_ret);
1328
1329 {
1330 XrdSysCondVarHelper lock(&m_active_cond);
1331 m_active.erase(it);
1332 m_active_cond.Broadcast();
1333 }
1334
1335 return std::min(f_ret, i_ret);
1336}
1337
1338//---------------------------------------------------------------------
1342//---------------------------------------------------------------------
1343bool Cache::is_http_cache_valid(const std::string& f_name,const std::string& i_name, XrdCl::URL& url)
1344{
1345 std::string icc;
1346
1347 // return true if nothing is written in cinfo extended file attributes
1348 if (GetCacheControlXAttr(i_name, icc) <= 0)
1349 return true;
1350
1351 bool ccIsValid = true;
1352 using namespace nlohmann;
1353 json cc_json = json::parse(icc);
1354
1355 bool mustRevalidate = cc_json.contains("revalidate") && (cc_json["revalidate"] == true);
1356 bool hasExpired = false;
1357 if (cc_json.contains("expire"))
1358 {
1359 time_t current_time;
1360 current_time = time(NULL);
1361 if (current_time > cc_json["expire"])
1362 hasExpired = true;
1363 }
1364
1365 if (cc_json.contains("ETag") && (mustRevalidate || hasExpired))
1366 {
1367 // Compare cinfo etag and the etag from file system query response
1368 // Add XrdCl:URL parameter as additional XrdOucCacheOp::Code::QFSinfo sub-command
1369 url.SetParam("code", "head");
1370 std::string response;
1371 std::string fsctlarg = url.GetURL();
1372 int st = XrdPosixExtra::FSctl(XrdOucCacheOp::Code::QFSinfo, fsctlarg, response, false, m_configuration.m_qfsredir);
1373
1374 if (st >= 0)
1375 {
1376 // client response keeps the \0 at the end of the string
1377 std::string etag = response.substr(0, response.find('\0'));
1378 std::string jval = cc_json["ETag"].get<std::string>();
1379 ccIsValid = (etag == jval);
1380
1381 TRACE(Info, "Prepare " << i_name << ", ETag valid res: " << ccIsValid);
1382
1383 // update expiration time if Etag is valid
1384 if (cc_json.contains("max-age"))
1385 {
1386 time_t ma = cc_json["max-age"];
1387 cc_json["expire"] = ma + time(NULL);
1388 char pfn[4096];
1389 m_oss->Lfn2Pfn(i_name.c_str(), pfn, 4096);
1390 WriteCacheControlXAttr(-1, pfn, cc_json.dump());
1391 }
1392 }
1393 else
1394 {
1395 // Message has a status because we are in the block condition for cache-control xattr
1396 TRACE(Error, "Prepare() XrdCl::FileSystem::Query failed " << f_name.c_str());
1397 ccIsValid = false;
1398 }
1399 }
1400
1401 return ccIsValid;
1402}
int DoIt(int argpnt, int argc, char **argv, bool singleshot)
#define TRACE_Debug
nlohmann::json json
#define XrdOssOK
Definition XrdOss.hh:54
std::string obfuscateAuth(const std::string &input)
#define TRACE_Dump
#define TRACE_PC(act, pre_code, x)
#define TRACE_INT(act, x)
void * ProcessWriteTaskThread(void *)
Definition XrdPfc.cc:64
XrdSysXAttr * XrdSysXAttrActive
void * ResourceMonitorThread(void *)
Definition XrdPfc.cc:58
void * PrefetchThread(void *)
Definition XrdPfc.cc:70
XrdOucCache * XrdOucGetCache(XrdSysLogger *logger, const char *config_filename, const char *parameters, XrdOucEnv *env)
Definition XrdPfc.cc:80
#define stat(a, b)
Definition XrdPosix.hh:105
bool Debug
#define TRACE(act, x)
Definition XrdTrace.hh:63
URL representation.
Definition XrdClURL.hh:31
const std::string & GetPath() const
Get the path.
Definition XrdClURL.hh:217
std::string GetURL() const
Get the URL.
Definition XrdClURL.hh:86
void SetParam(const std::string &name, const std::string &value)
Set a single param.
Definition XrdClURL.hh:283
virtual int Close(long long *retsz=0)=0
virtual int Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv &env)
Definition XrdOss.hh:228
virtual int Lfn2Pfn(const char *Path, char *buff, int blen)
Definition XrdOss.hh:954
virtual int Fstat(struct stat &sbuff)
virtual const char * Path()=0
virtual const char * Location(bool refresh=false)
static const int optRW
File is read/write (o/w read/only).
XrdOucCache(const char *ctype)
void * GetPtr(const char *varname)
Definition XrdOucEnv.cc:263
void PutPtr(const char *varname, void *value)
Definition XrdOucEnv.cc:298
XrdPfcFSctl(XrdPfc::Cache &cInst, XrdSysLogger *logP)
Constructor.
int get_size() const
long long m_offset
File * get_file() const
Attaches/creates and detaches/deletes cache-io objects for disk based cache.
Definition XrdPfc.hh:185
long long DetermineFullFileSize(const std::string &cinfo_fname)
Definition XrdPfc.cc:951
void FileSyncDone(File *, bool high_debug)
Definition XrdPfc.cc:553
File * GetFile(const std::string &, IO *, long long off=0, long long filesize=0)
Definition XrdPfc.cc:397
static const Configuration & Conf()
Definition XrdPfc.cc:138
bool Config(const char *config_filename, const char *parameters, XrdOucEnv *env)
Parse configuration file.
virtual int LocalFilePath(const char *url, char *buff=0, int blen=0, LFP_Reason why=ForAccess, bool forall=false)
Definition XrdPfc.cc:805
virtual int Stat(const char *url, struct stat &sbuff)
Definition XrdPfc.cc:1196
const Configuration & RefConfiguration() const
Reference XrdPfc configuration.
Definition XrdPfc.hh:241
static ResourceMonitor & ResMon()
Definition XrdPfc.cc:139
bool IsFileActiveOrPurgeProtected(const std::string &) const
Definition XrdPfc.cc:688
void ClearPurgeProtectedSet()
Definition XrdPfc.cc:696
void ReleaseRAM(char *buf, long long size)
Definition XrdPfc.cc:379
virtual int ConsiderCached(const char *url)
Definition XrdPfc.cc:1066
static Cache & GetInstance()
Singleton access.
Definition XrdPfc.cc:136
int GetCacheControlXAttr(const std::string &cinfo_fname, std::string &res) const
Definition XrdPfc.cc:991
void DeRegisterPrefetchFile(File *)
Definition XrdPfc.cc:722
void ExecuteCommandUrl(const std::string &command_url)
void RegisterPrefetchFile(File *)
Definition XrdPfc.cc:706
void WriteFileSizeXAttr(int cinfo_fd, long long file_size)
Definition XrdPfc.cc:936
void Prefetch()
Definition XrdPfc.cc:763
void ReleaseFile(File *, IO *)
Definition XrdPfc.cc:482
void AddWriteTask(Block *b, bool from_read)
Add downloaded block in write queue.
Definition XrdPfc.cc:229
Cache(XrdSysLogger *logger, XrdOucEnv *env)
Constructor.
Definition XrdPfc.cc:162
bool Decide(XrdOucCacheIO *)
Makes decision if the original XrdOucCacheIO should be cached.
Definition XrdPfc.cc:141
int UnlinkFile(const std::string &f_name, bool fail_if_open)
Remove cinfo and data files from cache.
Definition XrdPfc.cc:1267
static XrdScheduler * schedP
Definition XrdPfc.hh:328
File * GetNextFileToPrefetch()
Definition XrdPfc.cc:744
long long WritesSinceLastCall()
Definition XrdPfc.cc:328
void ProcessWriteTasks()
Separate task which writes blocks from ram to disk.
Definition XrdPfc.cc:281
virtual int Unlink(const char *url)
Definition XrdPfc.cc:1257
void WriteCacheControlXAttr(int cinfo_fd, const char *path, const std::string &cc)
Definition XrdPfc.cc:923
void RemoveWriteQEntriesFor(File *f)
Remove blocks from write queue which belong to given prefetch. This method is used at the time of Fil...
Definition XrdPfc.cc:248
virtual XrdOucCacheIO * Attach(XrdOucCacheIO *, int Options=0)
Definition XrdPfc.cc:183
static const Cache & TheOne()
Definition XrdPfc.cc:137
char * RequestRAM(long long size)
Definition XrdPfc.cc:339
virtual int Prepare(const char *url, int oflags, mode_t mode)
Definition XrdPfc.cc:1132
bool DecideIfConsideredCached(long long file_size, long long bytes_on_disk)
Definition XrdPfc.cc:1033
static Cache & CreateInstance(XrdSysLogger *logger, XrdOucEnv *env)
Singleton creation.
Definition XrdPfc.cc:129
bool is_prefetch_enabled() const
Definition XrdPfc.hh:333
Base class for selecting which files should be cached.
virtual bool Decide(const std::string &, XrdOss &) const =0
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.
void WriteBlockToDisk(Block *b)
int GetNBlocks() const
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.
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.
int inc_ref_cnt()
const Stats & RefStats() const
void Sync()
Sync file cache inf o and output data with disk.
int dec_ref_cnt()
int get_ref_cnt()
long long initiate_emergency_shutdown()
long long GetFileSize() const
const std::string & GetLocalPath() const
void RemoveIO(IO *io)
bool is_in_emergency_shutdown()
IOFileBlock(XrdOucCacheIO *io, Cache &cache)
Downloads original file into a single file on local disk. Handles read requests as they come along.
bool HasFile() const
Check if File was opened successfully.
IOFile(XrdOucCacheIO *io, Cache &cache)
Base cache-io class that implements some XrdOucCacheIO abstract methods.
Definition XrdPfcIO.hh:16
XrdOucCacheIO * GetInput()
Definition XrdPfcIO.cc:31
Status of cached file. Can be read from and written into a binary file.
Definition XrdPfcInfo.hh:41
static const char * s_infoExtension
void WriteIOStatSingle(long long bytes_disk)
Write single open/close time for given bytes read from disk.
bool Write(XrdOssDF *fp, const char *dname, const char *fname=0)
bool IsComplete() const
Get complete status.
long long GetFileSize() const
Get file size.
bool Read(XrdOssDF *fp, const char *dname, const char *fname=0)
Read content of cinfo file into this object.
int m_NCksumErrors
number of checksum errors while getting data from remote
long long m_BytesWritten
number of bytes written to disk
static int FSctl(XrdOucCacheOp::Code opc, const std::string &args, std::string &resp, bool viaCache=false, bool viaRedir=false)
void Schedule(XrdJob *jp)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
static void Wait(int milliseconds)
virtual int Get(const char *Aname, void *Aval, int Avsz, const char *Path, int fd=-1)=0
virtual int Set(const char *Aname, const void *Aval, int Avsz, const char *Path, int fd=-1, int isNew=0)=0
XrdPosixStats Stats
Contains parameters configurable from the xrootd config file.
Definition XrdPfc.hh:67
bool m_qfsredir
redirect file system query to the origin
Definition XrdPfc.hh:141
long long BytesHit
read from cache
Definition XrdPfcInfo.hh:64
long long BytesBypassed
read from remote and dropped
Definition XrdPfcInfo.hh:66
time_t DetachTime
close time
Definition XrdPfcInfo.hh:59
long long BytesMissed
read from remote and cached
Definition XrdPfcInfo.hh:65
time_t AttachTime
open time
Definition XrdPfcInfo.hh:58