XRootD
Loading...
Searching...
No Matches
XrdPfcIOFile.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 "XrdPfcIOFile.hh"
20#include "XrdPfcStats.hh"
21#include "XrdPfcTrace.hh"
22
23#include "XrdOss/XrdOss.hh"
25#include "XrdSys/XrdSysError.hh"
26
27#include "XrdOuc/XrdOucEnv.hh"
29
30#include <cstdio>
31#include <fcntl.h>
32
33using namespace XrdPfc;
34
35//______________________________________________________________________________
37 IO(io, cache),
38 m_file(0)
39{
40 m_file = Cache::GetInstance().GetFile(GetFilename(), this);
41}
42
43//______________________________________________________________________________
45{
46 // called from Detach() if no sync is needed or
47 // from Cache's sync thread
48 TRACEIO(Debug, "~IOFile() " << this);
49}
50
51//______________________________________________________________________________
52int IOFile::Fstat(struct stat &sbuff)
53{
54 // This is only called during Cache::Attach / Cache::GetFile() for file creation.
55 // Should really be separate name but one needs to change virtual interface
56 // so initialStat() becomes virtual in the base-class.
57 // Also, IOFileBlock should be ditched.
58 if ( ! m_file) {
59 return initialStat(sbuff);
60 }
61
62 return m_file->Fstat(sbuff);
63}
64
65//______________________________________________________________________________
66long long IOFile::FSize()
67{
68 return m_file->GetFileSize();
69}
70
71//______________________________________________________________________________
72int IOFile::initialStat(struct stat &sbuff)
73{
74 // Get stat to determine file-size.
75 // Called indirectly from the constructor, via Cache::GetFile().
76 // Either read it from cinfo file or obtain it from the remote IO.
77
78 static const char* trace_pfx = "initialStat ";
79
80 std::string fname = GetFilename();
81 std::string iname = fname + Info::s_infoExtension;
82 if (m_cache.GetOss()->Stat(iname.c_str(), &sbuff) == XrdOssOK &&
83 m_cache.GetOss()->Stat(fname.c_str(), &sbuff) == XrdOssOK)
84 {
85 long long file_size = m_cache.DetermineFullFileSize(fname + Info::s_infoExtension);
86 if (file_size >= 0)
87 {
88 sbuff.st_size = file_size;
89 TRACE(Info, trace_pfx << "successfully read size " << sbuff.st_size << " from info file " << iname);
90 return 0;
91 }
92 TRACE(Error, trace_pfx << "failed reading from info file " << iname << " " << XrdSysE2T(-file_size));
93 }
94
95 int res = GetInput()->Fstat(sbuff);
96 TRACEIO(Debug, trace_pfx << "stat from client res = " << res << ", size = " << sbuff.st_size);
97
98 return res;
99}
100
101//______________________________________________________________________________
103{
104 IO::Update(iocp);
105 m_file->ioUpdated(this);
106}
107
108//______________________________________________________________________________
110{
112 return m_file->ioActive(this);
113}
114
115//______________________________________________________________________________
117{
118 // Effectively a destructor.
119
120 TRACE(Debug, "DetachFinalize() " << this);
121
122 m_file->RequestSyncOfDetachStats();
123 Cache::GetInstance().ReleaseFile(m_file, this);
124
125 if (( ! m_error_counts.empty() || m_incomplete_count > 0) && XRD_TRACE What >= TRACE_Error) {
126 char info[1024];
127 int pos = 0, cap = 1024;
128 bool truncated = false;
129 for (auto [err, cnt] : m_error_counts) {
130 int len = snprintf(&info[pos], cap, " ( %d : %d)", err, cnt);
131 if (len >= cap) {
132 truncated = true;
133 break;
134 }
135 pos += len;
136 cap -= len;
137 }
138 TRACE(Error, "DetachFinalize() " << this << " n_incomplete_reads=" << m_incomplete_count
139 << ", block (error : count) report:" << info << (truncated ? " - truncated" : ""));
140 }
141
142 delete this;
143}
144
145
146//==============================================================================
147// Read and pgRead - sync / async and helpers
148//==============================================================================
149
150//______________________________________________________________________________
151int IOFile::Read(char *buff, long long off, int size)
152{
154
155 auto *rh = new ReadReqRHCond(ObtainReadSid(), nullptr);
156
157 TRACEIO(Dump, "Read() sync " << this << " sid: " << Xrd::hex1 << rh->m_seq_id << " off: " << off << " size: " << size);
158
159 rh->m_cond.Lock();
160 int retval = ReadBegin(buff, off, size, rh);
161 if (retval == kReadPending)
162 {
163 rh->m_cond.Wait();
164 retval = rh->m_retval;
165 }
166 rh->m_cond.UnLock();
167
168 return ReadEnd(retval, rh);
169}
170
171//______________________________________________________________________________
172void IOFile::Read(XrdOucCacheIOCB &iocb, char *buff, long long off, int size)
173{
174 struct ZHandler : ReadReqRH
175 { using ReadReqRH::ReadReqRH;
176 IOFile *m_io = nullptr;
177
178 void Done(int result) override {
179 m_io->ReadEnd(result, this);
180 }
181 };
182
184
185 auto *rh = new ZHandler(ObtainReadSid(), &iocb);
186 rh->m_io = this;
187
188 TRACEIO(Dump, "Read() async " << this << " sid: " << Xrd::hex1 << rh->m_seq_id << " off: " << off << " size: " << size);
189
190 int retval = ReadBegin(buff, off, size, rh);
191 if (retval != kReadPending)
192 {
193 rh->Done(retval);
194 }
195}
196
197//______________________________________________________________________________
198void IOFile::pgRead(XrdOucCacheIOCB &iocb, char *buff, long long off, int size,
199 std::vector<uint32_t> &csvec, uint64_t opts, int *csfix)
200{
201 struct ZHandler : ReadReqRH
202 { using ReadReqRH::ReadReqRH;
203 IOFile *m_io = nullptr;
204 std::function<void (int)> m_lambda {0};
205
206 void Done(int result) override {
207 if (m_lambda) m_lambda(result);
208 m_io->ReadEnd(result, this);
209 }
210 };
211
213
214 auto *rh = new ZHandler(ObtainReadSid(), &iocb);
215 rh->m_io = this;
216
217 TRACEIO(Dump, "pgRead() async " << this << " sid: " << Xrd::hex1 << rh->m_seq_id << " off: " << off << " size: " << size);
218
220 rh->m_lambda = [=, &csvec](int result) {
221 if (result > 0)
222 XrdOucPgrwUtils::csCalc((const char *)buff, (ssize_t)off, (size_t)result, csvec);
223 };
224
225 int retval = ReadBegin(buff, off, size, rh);
226 if (retval != kReadPending)
227 {
228 rh->Done(retval);
229 }
230}
231
232//______________________________________________________________________________
233int IOFile::ReadBegin(char *buff, long long off, int size, ReadReqRH *rh)
234{
235 // protect from reads over the file size
236 if (off >= FSize()) {
237 size = 0;
238 return 0;
239 }
240 if (off < 0) {
241 return -EINVAL;
242 }
243 if (off + size > FSize()) {
244 size = FSize() - off;
245 }
246 rh->m_expected_size = size;
247
248 return m_file->Read(this, buff, off, size, rh);
249}
250
251//______________________________________________________________________________
252int IOFile::ReadEnd(int retval, ReadReqRH *rh)
253{
254 TRACEIO(Dump, "ReadEnd() " << (rh->m_iocb ? "a" : "") << "sync " << this << " sid: " << Xrd::hex1 << rh->m_seq_id << " retval: " << retval << " expected_size: " << rh->m_expected_size);
255
256 if (retval < 0) {
257 TRACEIO(Debug, "ReadEnd() error in File::Read(), exit status=" << retval << ", error=" << XrdSysE2T(-retval) << " sid: " << Xrd::hex1 << rh->m_seq_id);
258 } else if (retval < rh->m_expected_size) {
259 TRACEIO(Debug, "ReadEnd() bytes missed " << rh->m_expected_size - retval << " sid: " << Xrd::hex1 << rh->m_seq_id);
260 }
261 if (rh->m_iocb)
262 rh->m_iocb->Done(retval);
263
264 delete rh;
265
267
268 return retval;
269}
270
271
272//==============================================================================
273// ReadV
274//==============================================================================
275
276//______________________________________________________________________________
277int IOFile::ReadV(const XrdOucIOVec *readV, int n)
278{
280
281 auto *rh = new ReadReqRHCond(ObtainReadSid(), nullptr);
282
283 TRACEIO(Dump, "ReadV() sync " << this << " sid: " << Xrd::hex1 << rh->m_seq_id << " n_chunks: " << n);
284
285 rh->m_cond.Lock();
286 int retval = ReadVBegin(readV, n, rh);
287 if (retval == kReadPending)
288 {
289 rh->m_cond.Wait();
290 retval = rh->m_retval;
291 }
292 rh->m_cond.UnLock();
293 return ReadVEnd(retval, rh);
294}
295
296//______________________________________________________________________________
297void IOFile::ReadV(XrdOucCacheIOCB &iocb, const XrdOucIOVec *readV, int n)
298{
299 struct ZHandler : ReadReqRH
300 { using ReadReqRH::ReadReqRH;
301 IOFile *m_io = nullptr;
302
303 void Done(int result) override { m_io-> ReadVEnd(result, this); }
304 };
305
307
308 auto *rh = new ZHandler(ObtainReadSid(), &iocb);
309 rh->m_io = this;
310
311 TRACEIO(Dump, "ReadV() async " << this << " sid: " << Xrd::hex1 << rh->m_seq_id << " n_chunks: " << n);
312
313 int retval = ReadVBegin(readV, n, rh);
314 if (retval != kReadPending)
315 {
316 rh->Done(retval);
317 }
318}
319
320//______________________________________________________________________________
321int IOFile::ReadVBegin(const XrdOucIOVec *readV, int n, ReadReqRH *rh)
322{
323 long long file_size = FSize();
324 for (int i = 0; i < n; ++i)
325 {
326 const XrdOucIOVec &vr = readV[i];
327 if (vr.offset < 0 || vr.offset >= file_size ||
328 vr.offset + vr.size > file_size)
329 {
330 return -EINVAL;
331 }
332 rh->m_expected_size += vr.size;
333 }
334 rh->m_n_chunks = n;
335
336 return m_file->ReadV(this, readV, n, rh);
337}
338
339//______________________________________________________________________________
340int IOFile::ReadVEnd(int retval, ReadReqRH *rh)
341{
342 TRACEIO(Dump, "ReadVEnd() " << (rh->m_iocb ? "a" : "") << "sync " << this << " sid: " << Xrd::hex1 << rh->m_seq_id <<
343 " retval: " << retval << " n_chunks: " << rh->m_n_chunks << " expected_size: " << rh->m_expected_size);
344
345 if (retval < 0) {
346 TRACEIO(Debug, "ReadVEnd() error in File::ReadV(), exit status=" << retval << ", error=" << XrdSysE2T(-retval));
347 } else if (retval < rh->m_expected_size) {
348 TRACEIO(Debug, "ReadVEnd() bytes missed " << rh->m_expected_size - retval);
349 }
350 if (rh->m_iocb)
351 rh->m_iocb->Done(retval);
352
353 delete rh;
354
356
357 return retval;
358}
#define XrdOssOK
Definition XrdOss.hh:50
#define TRACE_Error
Definition XrdPfcTrace.hh:7
#define TRACEIO(act, x)
#define stat(a, b)
Definition XrdPosix.hh:101
#define XRD_TRACE
bool Debug
struct myOpts opts
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
#define TRACE(act, x)
Definition XrdTrace.hh:63
virtual int Stat(const char *path, struct stat *buff, int opts=0, XrdOucEnv *envP=0)=0
virtual void Done(int result)=0
virtual int Fstat(struct stat &sbuff)
static const uint64_t forceCS
XrdOucCacheIO()
Construct and Destructor.
static void csCalc(const char *data, off_t offs, size_t count, uint32_t *csval)
Attaches/creates and detaches/deletes cache-io objects for disk based cache.
Definition XrdPfc.hh:163
long long DetermineFullFileSize(const std::string &cinfo_fname)
Definition XrdPfc.cc:928
File * GetFile(const std::string &, IO *, long long off=0, long long filesize=0)
Definition XrdPfc.cc:389
static Cache & GetInstance()
Singleton access.
Definition XrdPfc.cc:132
void ReleaseFile(File *, IO *)
Definition XrdPfc.cc:473
XrdOss * GetOss() const
Definition XrdPfc.hh:280
void Update(XrdOucCacheIO &iocp) override
void DetachFinalize() override
Abstract virtual method of XrdPfc::IO Called to destruct the IO object after it is no longer used.
int Read(char *buff, long long off, int size) override
Pass Read request to the corresponding File object.
int Fstat(struct stat &sbuff) override
bool ioActive() override
Abstract virtual method of XrdPfc::IO Called to check if destruction needs to be done in a separate t...
void pgRead(XrdOucCacheIOCB &iocb, char *buff, long long off, int size, std::vector< uint32_t > &csvec, uint64_t opts=0, int *csfix=0) override
int ReadV(const XrdOucIOVec *readV, int n) override
Pass ReadV request to the corresponding File object.
long long FSize() override
IOFile(XrdOucCacheIO *io, Cache &cache)
IO(XrdOucCacheIO *io, Cache &cache)
Definition XrdPfcIO.cc:7
int m_incomplete_count
Definition XrdPfcIO.hh:88
std::map< int, int > m_error_counts
Definition XrdPfcIO.hh:89
XrdOucCacheIO * GetInput()
Definition XrdPfcIO.cc:31
Cache & m_cache
reference to Cache object
Definition XrdPfcIO.hh:50
RAtomic_int m_active_read_reqs
number of active read requests
Definition XrdPfcIO.hh:70
const char * RefreshLocation()
Definition XrdPfcIO.hh:55
void Update(XrdOucCacheIO &iocp) override
Definition XrdPfcIO.cc:17
unsigned short ObtainReadSid()
Definition XrdPfcIO.hh:57
std::string GetFilename()
Definition XrdPfcIO.cc:36
Status of cached file. Can be read from and written into a binary file.
Definition XrdPfcInfo.hh:41
static const char * s_infoExtension
constexpr int kReadPending
Definition XrdPfcFile.hh:54
long long offset
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