XRootD
Loading...
Searching...
No Matches
XrdXrootdFile.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d X r o o t d F i l e . c c */
4/* */
5/* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <cinttypes>
31#include <cstdlib>
32#include <cstring>
33#include <unistd.h>
34#include <netinet/in.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37
38#include "XrdSys/XrdSysError.hh"
47#define TRACELINK this
49
50/******************************************************************************/
51/* G l o b a l s */
52/******************************************************************************/
53
54#ifndef NODEBUG
56#endif
57
58 XrdXrootdFileLock *XrdXrootdFile::Locker;
59
60 int XrdXrootdFile::sfOK = 1;
61 const char *XrdXrootdFile::TraceID = "File";
62 const char *XrdXrootdFileTable::TraceID = "FileTable";
63 const char *XrdXrootdFileTable::ID = "";
64
66
67namespace
68{
70
71static const unsigned long heldSpotV = 1UL;;
72
73static const unsigned long heldMask = ~1UL;
74}
75
76/******************************************************************************/
77/* x r d _ F i l e C l a s s */
78/******************************************************************************/
79/******************************************************************************/
80/* C o n s t r u c t o r */
81/******************************************************************************/
82
83XrdXrootdFile::XrdXrootdFile(const char *id, const char *path, XrdSfsFile *fp,
84 char mode, bool async, struct stat *sP)
85 : XrdSfsp(fp), mmAddr(0), FileKey(strdup(path)),
86 FileMode(mode), AsyncMode(async),
87 aioFob(0), pgwFob(0), fhProc(0),
88 ID(id), refCount(0), syncWait(0)
89{
90 static XrdSysMutex seqMutex;
91 struct stat buf;
92 off_t mmSize;
93
94// Initialize statistical counters
95//
96 Stats.Init();
97
98// Get the file descriptor number for sendfile() processing
99//
100 if (!sfOK || fp->fctl(SFS_FCTL_GETFD, 0, fp->error) != SFS_OK)
101 {fdNum = -1;
102 sfEnabled = false;
103 } else {
104 fdNum = fp->error.getErrInfo();
105 sfEnabled = (fdNum >= 0 || fdNum == (int)SFS_SFIO_FDVAL);
106 }
107
108// Determine if file is memory mapped
109//
110 if (fp->getMmap((void **)&mmAddr, mmSize) != SFS_OK) isMMapped = false;
111 else {isMMapped = (mmSize ? true : false);
112 Stats.fSize = static_cast<long long>(mmSize);
113 }
114
115// Get file status information (we need it) and optionally return it to caller
116//
117 if (sP || !isMMapped)
118 {if (!sP) sP = &buf;
119 fp->stat(sP);
120 if (!isMMapped) Stats.fSize = static_cast<long long>(sP->st_size);
121 }
122}
123
124/******************************************************************************/
125/* I n i t */
126/******************************************************************************/
127
129{
130 Locker = lp;
131 eDest = erP;
132 sfOK = sfok;
133}
134
135/******************************************************************************/
136/* D e s t r u c t o r */
137/******************************************************************************/
138
140{
141 if (aioFob) aioFob->Reset();
142
143 Serialize(); // Make sure there are no outstanding references
144
145 if (XrdSfsp)
146 {TRACEI(FS, "closing " <<FileMode <<' ' <<FileKey);
147 delete XrdSfsp;
148 XrdSfsp = 0;
149 Locker->Unlock(FileKey, FileMode);
150 }
151
152 if (fhProc) fhProc->Avail(fHandle);
153
154 if (aioFob) delete aioFob;
155
156 if (pgwFob) delete pgwFob;
157
158 if (FileKey) free(FileKey); // Must be the last thing deleted!
159}
160
161/******************************************************************************/
162/* R e f */
163/******************************************************************************/
164
166{
167
168// Change the reference counter and check if anyone is waiting
169//
170 fileMutex.Lock();
171 refCount += num;
172 TRACEI(FSAIO,"File::Ref="<<refCount<<" after +"<<num<<' '<<FileKey);
173 if (num < 0 && syncWait && refCount <= 0)
174 {syncWait->Post();
175 syncWait = nullptr;
176 }
177 fileMutex.UnLock();
178}
179
180/******************************************************************************/
181/* S e r i a l i z e */
182/******************************************************************************/
183
185{
186
187// Wait until the reference count reaches zero
188//
189 fileMutex.Lock();
190 TRACEI(FSAIO, "serializing access "<<FileMode<<" Ref="<<refCount<<' '<<FileKey);
191 if (refCount > 0)
192 {XrdSysSemaphore mySem(0);
193 syncWait = &mySem;
194 fileMutex.UnLock();
195 mySem.Wait();
196 } else fileMutex.UnLock();
197}
198
199/******************************************************************************/
200/* x r d _ F i l e T a b l e C l a s s */
201/******************************************************************************/
202/******************************************************************************/
203/* A d d */
204/******************************************************************************/
205
207{
208 const int allocsz = XRD_FTABSIZE*sizeof(fp);
209 XrdXrootdFile **newXTab, **oldXTab;
210 int i;
211
212// If we have a file handle processor, see if it can give us a file handle
213// that's already in our table.
214//
215 if (fhProc && (i = fhProc->Get()) >= 0)
216 {XrdXrootdFile **fP;
217 if (i < XRD_FTABSIZE) fP = &FTab[i];
218 else {i -= XRD_FTABSIZE;
219 if (XTab && i < XTnum) fP = &XTab[i];
220 else fP = 0;
221 i += XRD_FTABSIZE;
222 }
223 if (fP && *fP == heldSpotP)
224 {*fP = fp;
225 TRACEI(FS, "reusing fh " <<i <<" for " <<fp->FileKey);
226 return i;
227 }
228 char fhn[32];
229 snprintf(fhn, sizeof(fhn), "%d", i);
230 eDest->Emsg("FTab_Add", "Invalid recycled fHandle",fhn,"ignored.");
231 }
232
233// Find a free spot in the internal table
234//
235 for (i = FTfree; i < XRD_FTABSIZE; i++) if (!FTab[i]) break;
236
237 if (i < XRD_FTABSIZE)
238 {FTab[i] = fp; FTfree = i+1; return i;}
239
240// Allocate an external table if we do not have one
241//
242 if (!XTab)
243 {if (!(XTab = (XrdXrootdFile **)malloc(allocsz))) return -1;
244 memset((void *)XTab, 0, allocsz);
245 XTnum = XRD_FTABSIZE;
246 XTfree = 1;
247 XTab[0] = fp;
248 return XRD_FTABSIZE;
249 }
250
251// Find a free spot in the external table
252//
253 for (i = XTfree; i < XTnum; i++) if (!XTab[i]) break;
254 if (i < XTnum)
255 {XTab[i] = fp; XTfree = i+1; return i+XRD_FTABSIZE;}
256
257// Extend the table
258//
259 if (!(newXTab = (XrdXrootdFile **)malloc(XTnum*sizeof(XrdXrootdFile *)+allocsz)))
260 return -1;
261 memcpy((void *)newXTab, (const void *)XTab, XTnum*sizeof(XrdXrootdFile *));
262 memset((void *)(newXTab+XTnum), 0, allocsz);
263 oldXTab = XTab;
264 XTab = newXTab;
265 XTab[XTnum] = fp;
266 i = XTnum;
267 XTfree = XTnum+1;
268 XTnum += XRD_FTABSIZE;
269 free(oldXTab);
270 return i+XRD_FTABSIZE;
271}
272
273/******************************************************************************/
274/* D e l */
275/******************************************************************************/
276
278 bool dodel)
279{
280 union {XrdXrootdFile *fp; unsigned long fv;};
281 XrdXrootdFile *repVal = (dodel ? 0 : heldSpotP);
282 int fh = fnum;
283
284 if (fnum < XRD_FTABSIZE)
285 {fp = FTab[fnum];
286 FTab[fnum] = repVal;
287 if (fnum < FTfree) FTfree = fnum;
288 } else {
289 fnum -= XRD_FTABSIZE;
290 if (XTab && fnum < XTnum)
291 {fp = XTab[fnum];
292 XTab[fnum] = repVal;
293 if (fnum < XTfree) XTfree = fnum;
294 }
295 else fp = 0;
296 }
297
298 fv &= heldMask;
299
300 if (fp)
301 {XrdXrootdFileStats &Stats = fp->Stats;
304
305 Stats.xfr.read += Stats.prw.rBytes;
306 Stats.xfr.write += Stats.prw.wBytes;
307 Stats.ops.read += Stats.prw.rCount;
308 Stats.ops.write += Stats.prw.wCount; // Doesn't include retries!!!
309
310 if (monP) monP->Close(Stats.FileID,
311 Stats.xfr.read + Stats.xfr.readv,
312 Stats.xfr.write);
313 if (Stats.MonEnt != -1) XrdXrootdMonFile::Close(&Stats, false);
314 if (dodel) {delete fp; fp = 0;} // Will do the close
315 else {if (!fhProc) fhProc = new XrdXrootdFileHP;
316 else fhProc->Ref();
317 fp->fHandle = fh;
318 fp->fhProc = fhProc;
319 TRACEI(FS, "defer fh " <<fh <<" del for " <<fp->FileKey);
320 }
321 }
322 return fp;
323}
324
325/******************************************************************************/
326/* R e c y c l e */
327/******************************************************************************/
328
329// WARNING! The object subject to this method must be serialized. There can
330// be no active requests on link associated with this object at the time the
331// destructor is called. The same restrictions apply to Add() and Del().
332//
334{
335 int i;
336
337// Delete all objects from the internal table (see warning)
338//
339 FTfree = 0;
340 for (i = 0; i < XRD_FTABSIZE; i++)
341 if (FTab[i] && FTab[i] != heldSpotP)
342 {XrdXrootdFileStats &Stats = FTab[i]->Stats;
343 if (monP) monP->Close(Stats.FileID,
344 Stats.xfr.read+Stats.xfr.readv,
345 Stats.xfr.write);
346 if (Stats.MonEnt != -1) XrdXrootdMonFile::Close(&Stats, true);
347 delete FTab[i]; FTab[i] = 0;
348 }
349
350// Delete all objects from the external table (see warning)
351//
352if (XTab)
353 {for (i = 0; i < XTnum; i++)
354 {if (XTab[i] && XTab[i] != heldSpotP)
355 {XrdXrootdFileStats &Stats = XTab[i]->Stats;
356 if (monP) monP->Close(Stats.FileID,
357 Stats.xfr.read+Stats.xfr.readv,
358 Stats.xfr.write);
359 if (Stats.MonEnt != -1) XrdXrootdMonFile::Close(&Stats, true);
360 delete XTab[i];
361 }
362 }
363 free(XTab); XTab = 0; XTnum = 0; XTfree = 0;
364 }
365
366// If we have a filehandle processor, delete it. Note that it will stay alive
367// until all requests for file handles against it are resolved.
368//
369 if (fhProc) fhProc->Delete();
370
371// Delete this object
372//
373 delete this;
374}
375
376/******************************************************************************/
377/* P r i v a t e M e t h o d s */
378/******************************************************************************/
379/******************************************************************************/
380/* b i n 2 h e x */
381/******************************************************************************/
382
383int XrdXrootdFile::bin2hex(char *outbuff, char *inbuff, int inlen)
384{
385 static const char hv[] = "0123456789abcdef";
386 int i, j = 0;
387
388// Skip leading zeroes
389//
390 for (i = 0; i < inlen; i++) if (inbuff[i]) break;
391 if (i >= inlen)
392 {outbuff[0] = '0'; outbuff[1] = '\0'; return 1;}
393
394// Format the data
395//
396 for ( ; i < inlen; i++)
397 {outbuff[j++] = hv[(inbuff[i] >> 4) & 0x0f];
398 outbuff[j++] = hv[ inbuff[i] & 0x0f];
399 }
400 outbuff[j] = '\0';
401 return j;
402}
static XrdSysError eDest(0,"crypto_")
#define stat(a, b)
Definition XrdPosix.hh:101
#define SFS_SFIO_FDVAL
#define SFS_FCTL_GETFD
#define SFS_OK
#define TRACEI(act, x)
Definition XrdTrace.hh:66
#define ID
XrdSysTrace XrdXrootdTrace
#define XRD_FTABSIZE
XrdOucErrInfo & error
virtual int getMmap(void **Addr, off_t &Size)=0
virtual int stat(struct stat *buf)=0
virtual int fctl(const int cmd, const char *args, XrdOucErrInfo &eInfo)=0
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Avail(int fHandle)
virtual int Unlock(const char *path, char mode)=0
void Recycle(XrdXrootdMonitor *monP)
int Add(XrdXrootdFile *fp)
static XrdXrootdFile * heldSpotP
XrdXrootdFile * Del(XrdXrootdMonitor *monP, int fnum, bool dodel=true)
XrdXrootdFileHP * fhProc
XrdXrootdFile(const char *id, const char *path, XrdSfsFile *fp, char mode='r', bool async=false, struct stat *sP=0)
void Ref(int num)
XrdXrootdPgwFob * pgwFob
static void Init(XrdXrootdFileLock *lp, XrdSysError *erP, bool sfok)
XrdSfsFile * XrdSfsp
XrdXrootdAioFob * aioFob
XrdXrootdFileStats Stats
static void Close(XrdXrootdFileStats *fsP, bool isDisc=false)
void Close(kXR_unt32 dictid, long long rTot, long long wTot)