XRootD
Loading...
Searching...
No Matches
XrdOfsHandle.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O f s H a n d l e . c c */
4/* */
5/* (c) 2008 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky for Stanford University under contract */
8/* DE-AC02-76-SFO0515 with the Department of Energy */
9/* */
10/* This file is part of the XRootD software suite. */
11/* */
12/* XRootD is free software: you can redistribute it and/or modify it under */
13/* the terms of the GNU Lesser General Public License as published by the */
14/* Free Software Foundation, either version 3 of the License, or (at your */
15/* option) any later version. */
16/* */
17/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20/* License for more details. */
21/* */
22/* You should have received a copy of the GNU Lesser General Public License */
23/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25/* */
26/* The copyright holder's institutional names and contributor's names may not */
27/* be used to endorse or promote products derived from this software without */
28/* specific prior written permission of the institution or contributor. */
29/******************************************************************************/
30
31#include <cstdio>
32#include <ctime>
33#include <errno.h>
34#include <sys/types.h>
35
37#include "XrdOfs/XrdOfsStats.hh"
38#include "XrdOss/XrdOss.hh"
39#include "XrdSys/XrdSysError.hh"
41#include "XrdSys/XrdSysTimer.hh"
42
43/******************************************************************************/
44/* L o c a l C l a s s e s */
45/******************************************************************************/
46/******************************************************************************/
47/* X r d O f s H a n O s s */
48/******************************************************************************/
49
50class XrdOfsHanOss : public XrdOssDF
51{
52public:
53 // Directory oriented methods
54 int Opendir(const char *, XrdOucEnv &) {return -EBADF;}
55 int Readdir(char *buff, int blen) {return rRC; }
56
57 // File oriented methods
58 int Fchmod(mode_t mode) {return wRC; }
59 int Fstat(struct stat *) {return rRC; }
60 int Fsync() {return wRC; }
61 int Fsync(XrdSfsAio *aiop) {return wRC; }
62 int Ftruncate(unsigned long long) {return wRC; }
63 off_t getMmap(void **addr) {return 0;}
64 int isCompressed(char *cxidp=0) {return 0;}
65 int Open(const char *, int, mode_t, XrdOucEnv &) {return -EBADF;}
66 ssize_t pgRead (void* buffer, off_t offset, size_t rdlen,
67 uint32_t* csvec, uint64_t opts) {return rRC; }
68 int pgRead (XrdSfsAio* aioparm, uint64_t opts) {return rRC; }
69 ssize_t pgWrite(void* buffer, off_t offset, size_t wrlen,
70 uint32_t* csvec, uint64_t opts) {return wRC; }
71 int pgWrite(XrdSfsAio* aioparm, uint64_t opts) {return wRC; }
72 ssize_t Read(off_t, size_t) {return rRC; }
73 ssize_t Read(void *, off_t, size_t) {return rRC; }
74 int Read(XrdSfsAio *aiop) {return rRC; }
75 ssize_t ReadV(XrdOucIOVec *readV,int rdvcnt) {return rRC; }
76 ssize_t ReadRaw( void *, off_t, size_t) {return rRC; }
77 ssize_t Write(const void *, off_t, size_t) {return wRC; }
78 int Write(XrdSfsAio *aiop) {return wRC; }
79 ssize_t WriteV(XrdOucIOVec *writeV, int wrvcnt) {return wRC; }
80
81 // Methods common to both
82 int Close(long long *retsz=0) {return -EBADF;}
83
84 XrdOfsHanOss(int rrc=-EBADF, int wrc=-EBADF)
85 : rRC(rrc), wRC(wrc) {}
87
88protected:
89int rRC;
90int wRC;
91};
92
93/******************************************************************************/
94/* X r d O f s H a n O s s E r r */
95/******************************************************************************/
96
98{
99public:
100 int Readdir(char *buff, int blen)
101 {return (rRC ? rRC : ossP->Readdir(buff, blen));}
102
103 int Fstat(struct stat *Stat) {return ossP->Fstat(Stat);}
104
105 ssize_t pgRead (void* buffer, off_t offset, size_t rdlen,
106 uint32_t* csvec, uint64_t opts)
107 {if (rRC) return rRC;
108 return ossP->pgRead(buffer,offset,rdlen,csvec,opts);
109 }
110
111 int pgRead (XrdSfsAio* aioparm, uint64_t opts)
112 {if (rRC) return rRC;
113 return ossP->pgRead(aioparm, opts);
114 }
115
116 ssize_t Read(off_t offset, size_t rlen)
117 {if (rRC) return rRC;
118 return ossP->Read(offset, rlen);
119 }
120
121 ssize_t Read(void *buff, off_t offset, size_t rlen)
122 {if (rRC) return rRC;
123 return ossP->Read(buff, offset, rlen);
124 }
125
126 int Read(XrdSfsAio *aiop)
127 {if (rRC) return rRC;
128 return ossP->Read(aiop);
129 }
130
131 ssize_t ReadV(XrdOucIOVec *readV,int rdvcnt)
132 {if (rRC) return rRC;
133 return ossP->ReadV(readV, rdvcnt);
134 }
135
136 ssize_t ReadRaw(void *buff , off_t offset, size_t rlen)
137 {if (rRC) return rRC;
138 return ossP->ReadRaw(buff, offset, rlen);
139 }
140
141 int Close(long long *retsz=0) {return ossP->Close(retsz);}
142
143 XrdOfsHanOssErr(XrdOssDF *ossp, int rrc=-EBADF, int wrc=-EBADF)
144 : XrdOfsHanOss(rrc, wrc), ossP(ossp)
145 {tident = ossp->getTID();
146 fd = ossp->getFD();
147 dfType = ossp->DFType();
148 }
149
151
152protected:
153
155};
156
157/******************************************************************************/
158/* X r d O f s H a n X p r */
159/******************************************************************************/
160
162{
163friend class XrdOfsHandle;
164public:
165
166 void add2Q(int doLK=1);
167
168 void Deref()
169 {xqCV.Lock(); Handle=0; Call=0; xTNew=0; xqCV.UnLock();}
170
171static XrdOfsHanXpr *Get();
172
173 void Set(XrdOfsHanCB *cbP, time_t xtm)
174 {xqCV.Lock(); Call = cbP; xTNew = xtm; xqCV.UnLock();}
175
176 XrdOfsHanXpr(XrdOfsHandle *hP, XrdOfsHanCB *cbP, time_t xtm)
177 : Next(0), Handle(hP), Call(cbP), xTime(xtm), xTNew(0) {}
179
180private:
181 XrdOfsHanXpr *Next;
182 XrdOfsHandle *Handle;
183 XrdOfsHanCB *Call;
184 time_t xTime;
185 time_t xTNew;
186
187static XrdSysCondVar xqCV;
188static XrdOfsHanXpr *xprQ;
189};
190
191XrdSysCondVar XrdOfsHanXpr::xqCV(0, "HanXpr cv");
192XrdOfsHanXpr *XrdOfsHanXpr::xprQ = 0;
193
194/******************************************************************************/
195/* X r d O f s H a n P s c */
196/******************************************************************************/
197
199{
200public:
201
202union {
204char *User; // -> Owner for posc files (user.pid:fd@host)
205 };
206XrdOfsHanXpr *xprP; // -> Associate Xpr object if active
207int Unum; // -> Offset in poscq
208short Ulen; // Length of user.pid
209short Uhst; // -> Host portion
210short Mode; // Mode file is to have
211
212static
214
215void Recycle();
216
217 XrdOfsHanPsc() : User(0), xprP(0), Unum(0), Ulen(0),
218 Uhst(0), Mode(0) {}
220private:
221
222static XrdSysMutex pscMutex;
223static XrdOfsHanPsc *Free;
224};
225
226XrdSysMutex XrdOfsHanPsc::pscMutex;
227XrdOfsHanPsc *XrdOfsHanPsc::Free = 0;
228
229/******************************************************************************/
230/* E x t e r n a l L i n k a g e s */
231/******************************************************************************/
232
233void *XrdOfsHanXpire(void *pp)
234{
236 return (void *)0;
237}
238
240
241extern XrdOfsStats OfsStats;
242
243/******************************************************************************/
244/* S t a t i c O b j e c t s */
245/******************************************************************************/
246
247XrdSysMutex XrdOfsHandle::myMutex;
248XrdOfsHanTab XrdOfsHandle::roTable;
249XrdOfsHanTab XrdOfsHandle::rwTable;
250XrdOssDF *XrdOfsHandle::ossDF = (XrdOssDF *)new XrdOfsHanOss;
251XrdOfsHandle *XrdOfsHandle::Free = 0;
252
253/******************************************************************************/
254/* c l a s s X r d O f s H a n d l e */
255/******************************************************************************/
256/******************************************************************************/
257/* static public A l l o c # 1 */
258/******************************************************************************/
259
260int XrdOfsHandle::Alloc(const char *thePath, int Opts, XrdOfsHandle **Handle)
261{
262 XrdOfsHandle *hP;
263 XrdOfsHanTab *theTable = (Opts & opRW ? &rwTable : &roTable);
264 XrdOfsHanKey theKey(thePath, (int)strlen(thePath));
265 int retc;
266
267// Lock the search table and try to find the key. If found, increment the
268// the link count (can only be done with the global lock) then release the
269// lock and try to lock the handle. It can't escape between lock calls because
270// the link count is positive. If we can't lock the handle then it must be the
271// that a long running operation is occuring. Return the handle to its former
272// state and return a delay. Otherwise, return the handle.
273//
274 myMutex.Lock();
275 if ((hP = theTable->Find(theKey)))
276 {hP->Path.Links++; myMutex.UnLock();
277 if (hP->WaitLock()) {*Handle = hP; return 0;}
278 myMutex.Lock(); hP->Path.Links--; myMutex.UnLock();
279 return nolokDelay;
280 }
281
282// Get a new handle
283//
284 if (!(retc = Alloc(theKey, Opts, Handle))) theTable->Add(*Handle);
285 OfsStats.Add(OfsStats.Data.numHandles);
286
287// All done
288//
289 myMutex.UnLock();
290 return retc;
291}
292
293/******************************************************************************/
294/* static public A l l o c # 2 */
295/******************************************************************************/
296
298{
299 XrdOfsHanKey myKey("dummy", 5);
300 int retc;
301
302 myMutex.Lock();
303 if (!(retc = Alloc(myKey, 0, Handle)))
304 {(*Handle)->Path.Links = 0; (*Handle)->UnLock();}
305 myMutex.UnLock();
306 return retc;
307}
308
309/******************************************************************************/
310/* private A l l o c # 3 */
311/******************************************************************************/
312
313int XrdOfsHandle::Alloc(XrdOfsHanKey theKey, int Opts, XrdOfsHandle **Handle)
314{
315 static const int minAlloc = 4096/sizeof(XrdOfsHandle);
316 XrdOfsHandle *hP;
317
318// No handle currently in the table. Get a new one off the free list
319//
320 if (!Free && (hP = new XrdOfsHandle[minAlloc]))
321 {int i = minAlloc; while(i--) {hP->Next = Free; Free = hP; hP++;}}
322 if ((hP = Free)) Free = hP->Next;
323
324// Initialize the new handle, if we have one, and add it to the table
325//
326 if (hP)
327 {hP->Path = theKey;
328 hP->Path.Links = 1;
329 hP->isChanged = 0; // File changed
330 hP->isCompressed = 0; // Compression
331 hP->isPending = 0; // Pending output
332 hP->isRW = (Opts & opPC); // File mode
333 hP->ssi = ossDF; // No storage system yet
334 hP->Posc = 0; // No creator
335 hP->Lock(); // Wait is not possible
336 *Handle = hP;
337 return 0;
338 }
339 return nomemDelay; // Delay client
340}
341
342/******************************************************************************/
343/* static public H i d e */
344/******************************************************************************/
345
346void XrdOfsHandle::Hide(const char *thePath)
347{
348 XrdOfsHandle *hP;
349 XrdOfsHanKey theKey(thePath, (int)strlen(thePath));
350
351// Lock the search table and try to find the key in each table. If found,
352// clear the length field to effectively hide the item.
353//
354 myMutex.Lock();
355 if ((hP = roTable.Find(theKey))) hP->Path.Len = 0;
356 if ((hP = rwTable.Find(theKey))) hP->Path.Len = 0;
357 myMutex.UnLock();
358}
359
360/******************************************************************************/
361/* public P o s c G e t */
362/******************************************************************************/
363
364// Warning: the handle must be locked!
365
366int XrdOfsHandle::PoscGet(short &Mode, int Done)
367{
368 XrdOfsHanPsc *pP;
369 int pnum;
370
371 if (Posc)
372 {pnum = Posc->Unum;
373 Mode = Posc->Mode;
374 if (Done)
375 {pP = Posc; Posc = 0;
376 if (pP->xprP) {myMutex.Lock(); Path.Links--; myMutex.UnLock();}
377 pP->Recycle();
378 }
379 return pnum;
380 }
381
382 Mode = 0;
383 return 0;
384}
385
386/******************************************************************************/
387/* public P o s c S e t */
388/******************************************************************************/
389
390// Warning: the handle must be locked!
391
392int XrdOfsHandle::PoscSet(const char *User, int Unum, short Umod)
393{
394 static const char *Who = "?:0.0@?", *Whc = Who+1, *Whh = Who+5;
395 const char *Col, *At;
396 int retval = 0;
397
398// If we have no posc object then we may just be able to return
399//
400 if (!Posc)
401 {if (Unum > 0) Posc = XrdOfsHanPsc::Alloc();
402 else return 0;
403 }
404
405// Find the markers in the incoming user
406//
407 if (!(Col = index(User, ':')) || !(At = index(User, '@')))
408 {User = Who; Col = Whc; At = Whh;}
409
410// If we already have a user check if it matches. We allow the same user to
411// reconnect to the file even when it is in posc mode to allow for write error
412// recovery. Other users must re-enable posc for the file to show that they are
413// aware that the file is under POSC mode as this is not a recovery.
414//
415 if (Posc->User)
416 {if (!Unum)
417 {if (!strncmp(User, Posc->User, Posc->Ulen)
418 && !strcmp(Posc->User + Posc->Uhst, At+1)) return 0;
419 return -ETXTBSY;
420 } else {
421 char buff[1024];
422 sprintf(buff, "%s to %s for", Posc->User, User);
423 OfsEroute.Emsg("Posc", "Creator changed from", buff, Path.Val);
424 if (Unum < 0) Unum = Posc->Unum;
425 else if (Unum != Posc->Unum) retval = Posc->Unum;
426 }
427 free(Posc->User);
428 }
429
430// Assign creation values
431//
432 Posc->User = strdup(User);
433 Posc->Ulen = Col - User + 1;
434 Posc->Uhst = At - User + 1;
435 Posc->Unum = Unum;
436 Posc->Mode = Umod;
437 return retval;
438}
439
440/******************************************************************************/
441/* public P o s c U s r */
442/******************************************************************************/
443
444// Warning: the handle must be locked!
445
447{
448 if (Posc) return Posc->User;
449 return "?@?";
450}
451
452/******************************************************************************/
453/* public R e t i r e */
454/******************************************************************************/
455
456// The handle must be locked upon entry! It is unlocked upon exit.
457
458int XrdOfsHandle::Retire(int &retc, long long *retsz, char *buff, int blen)
459{
460 XrdOssDF *mySSI;
461 int numLeft;
462
463// Get the global lock as the links field can only be manipulated with it.
464// Decrement the links count and if zero, remove it from the table and
465// place it on the free list. Otherwise, it is still in use.
466//
467 retc = 0;
468 myMutex.Lock();
469 if (Path.Links == 1)
470 {if (buff) strlcpy(buff, Path.Val, blen);
471 numLeft = 0; OfsStats.Dec(OfsStats.Data.numHandles);
472 if ( (isRW ? rwTable.Remove(this) : roTable.Remove(this)) )
473 {if (Posc) {Posc->Recycle(); Posc = 0;}
474 if (Path.Val) {free((void *)Path.Val); Path.Val = (char *)"";}
475 Path.Len = 0; mySSI = ssi; ssi = ossDF;
476 Next = Free; Free = this; UnLock(); myMutex.UnLock();
477 if (mySSI && mySSI != ossDF)
478 {retc = mySSI->Close(retsz); delete mySSI;}
479 } else {
480 UnLock(); myMutex.UnLock();
481 OfsEroute.Emsg("Retire", "Lost handle to", buff);
482 }
483 } else {numLeft = --Path.Links; UnLock(); myMutex.UnLock();}
484 return numLeft;
485}
486
487/******************************************************************************/
488
490{
491 static int allOK = StartXpr(1);
492 XrdOfsHanXpr *xP;
493 int retc;
494
495// The handle can only be held by one reference and only if it's a POSC and
496// deferred handling was properly set up.
497//
498 myMutex.Lock();
499 if (!Posc || !allOK)
500 {OfsEroute.Emsg("Retire", "ignoring deferred retire of", Path.Val);
501 if (Path.Links != 1 || !Posc || !cbP) myMutex.UnLock();
502 else {myMutex.UnLock(); cbP->Retired(this);}
503 return Retire(retc);
504 }
505 myMutex.UnLock();
506
507// If this object already has an xpr object (happens for bouncing connections)
508// then reuse that object. Otherwise create a new one and put it on the queue.
509//
510 if (Posc->xprP) Posc->xprP->Set(cbP, hTime+time(0));
511 else {xP = Posc->xprP = new XrdOfsHanXpr(this, cbP, hTime+time(0));
512 xP->add2Q();
513 }
514 UnLock();
515 return 0;
516}
517
518/******************************************************************************/
519/* public S t a r t X p r */
520/******************************************************************************/
521
523{
524 static int InitDone = 0;
525 XrdOfsHanXpr *xP;
526 XrdOfsHandle *hP;
527 int retc;
528
529// If this is the initial all and we have not been initialized do so
530//
531 if (Init)
532 {pthread_t tid;
533 int rc;
534 if (InitDone) return InitDone == 1;
535 if ((rc = XrdSysThread::Run(&tid, XrdOfsHanXpire, (void *)0,
536 0, "Handle Timeout")))
537 {OfsEroute.Emsg("StartXpr", rc, "create handle timeout thread");
538 InitDone = -1; return 0;
539 }
540 InitDone = 1; return 1;
541 }
542
543// Simply loop waiting for expired handles to become available. The Get() will
544// return an Xpr object with the associated handle locked.
545//
546do{xP = XrdOfsHanXpr::Get(); hP = xP->Handle;
547
548// Perform validity check on the handle to catch instances where the handle
549// was closed while we were in the process of getting it. While this is safe
550// it should never happen, so issue a message so we know to fix it.
551//
552 if (hP->Posc && xP == hP->Posc->xprP) hP->Posc->xprP = 0;
553 else {OfsEroute.Emsg("StarXtpr", "Invalid xpr ref to", hP->Path.Val);
554 hP->UnLock(); delete xP; continue;
555 }
556
557// As the handle is locked we can get the global handle lock to prevent
558// additions and removals of handles as we need a stable reference count to
559// effect the callout, if any. Do so only if the reference count is one (for us)
560// and the handle is active. In all cases, drop the global lock.
561//
562 myMutex.Lock();
563 if (hP->Path.Links != 1 || !xP->Call) myMutex.UnLock();
564 else {myMutex.UnLock();
565 xP->Call->Retired(hP);
566 }
567
568// We can now officially retire the handle and delete the xpr object
569//
570 hP->Retire(retc);
571 delete xP;
572 } while(1);
573
574// Keep the compiler happy
575//
576 return 0;
577}
578
579/******************************************************************************/
580/* public: S u p p r e s s */
581/******************************************************************************/
582
583void XrdOfsHandle::Suppress(int rrc, int wrc)
584{
585 ssi = new XrdOfsHanOssErr(ssi, rrc, wrc);
586}
587
588/******************************************************************************/
589/* public W a i t L o c k */
590/******************************************************************************/
591
592int XrdOfsHandle::WaitLock(void)
593{
594// Try to obtain a lock within the retry parameters
595//
596 if (hMutex.TimedLock(LockTries*LockWait)) return 1;
597 return 0;
598}
599
600/******************************************************************************/
601/* C l a s s X r d O f s H a n P s c */
602/******************************************************************************/
603/******************************************************************************/
604/* A l l o c */
605/******************************************************************************/
606
608{
609 XrdOfsHanPsc *pP;
610
611// Grab or allocate an object
612//
613 pscMutex.Lock();
614 if ((pP = Free)) {Free = pP->Next; pP->Next = 0;}
615 else pP = new XrdOfsHanPsc;
616 pscMutex.UnLock();
617
618 return pP;
619}
620
621/******************************************************************************/
622/* R e c y c l e */
623/******************************************************************************/
624
626{
627
628// Release any storgae appendages and clear other field
629//
630 if (xprP) {xprP->Deref(); xprP = 0;}
631 if (User) free(User);
632 Unum = 0;
633 Ulen = 0;
634 Uhst = 0;
635 Mode = 0;
636
637// Place element on free chain. We keep them all as there are never too many
638//
639 pscMutex.Lock();
640 Next = Free; Free = this;
641 pscMutex.UnLock();
642}
643
644/******************************************************************************/
645/* C l a s s X r d O f s H a n T a b */
646/******************************************************************************/
647/******************************************************************************/
648/* C o n s t r u c t o r */
649/******************************************************************************/
650
651XrdOfsHanTab::XrdOfsHanTab(int psize, int csize)
652{
653 prevtablesize = psize;
654 nashtablesize = csize;
655 Threshold = (csize * LoadMax) / 100;
656 nashnum = 0;
657 nashtable = (XrdOfsHandle **)
658 malloc( (size_t)(csize*sizeof(XrdOfsHandle *)) );
659 memset((void *)nashtable, 0, (size_t)(csize*sizeof(XrdOfsHandle *)));
660}
661
662/******************************************************************************/
663/* public A d d */
664/******************************************************************************/
665
667{
668 unsigned int kent;
669
670// Check if we should expand the table
671//
672 if (++nashnum > Threshold) Expand();
673
674// Add the entry to the table
675//
676 kent = hip->Path.Hash % nashtablesize;
677 hip->Next = nashtable[kent];
678 nashtable[kent] = hip;
679}
680
681/******************************************************************************/
682/* private E x p a n d */
683/******************************************************************************/
684
685void XrdOfsHanTab::Expand()
686{
687 int newsize, newent, i;
688 size_t memlen;
689 XrdOfsHandle **newtab, *nip, *nextnip;
690
691// Compute new size for table using a fibonacci series
692//
693 newsize = prevtablesize + nashtablesize;
694
695// Allocate the new table
696//
697 memlen = (size_t)(newsize*sizeof(XrdOfsHandle *));
698 if (!(newtab = (XrdOfsHandle **) malloc(memlen))) return;
699 memset((void *)newtab, 0, memlen);
700
701// Redistribute all of the current items
702//
703 for (i = 0; i < nashtablesize; i++)
704 {nip = nashtable[i];
705 while(nip)
706 {nextnip = nip->Next;
707 newent = nip->Path.Hash % newsize;
708 nip->Next = newtab[newent];
709 newtab[newent] = nip;
710 nip = nextnip;
711 }
712 }
713
714// Free the old table and plug in the new table
715//
716 free((void *)nashtable);
717 nashtable = newtab;
718 prevtablesize = nashtablesize;
719 nashtablesize = newsize;
720
721// Compute new expansion threshold
722//
723 Threshold = static_cast<int>((static_cast<long long>(newsize)*LoadMax)/100);
724}
725
726/******************************************************************************/
727/* public F i n d */
728/******************************************************************************/
729
731{
732 XrdOfsHandle *nip;
733 unsigned int kent;
734
735// Compute position of the hash table entry
736//
737 kent = Key.Hash%nashtablesize;
738
739// Find the entry
740//
741 nip = nashtable[kent];
742 while(nip && nip->Path != Key) nip = nip->Next;
743 return nip;
744}
745
746/******************************************************************************/
747/* public R e m o v e */
748/******************************************************************************/
749
751{
752 XrdOfsHandle *nip, *pip = 0;
753 unsigned int kent;
754
755// Compute position of the hash table entry
756//
757 kent = rip->Path.Hash%nashtablesize;
758
759// Find the entry
760//
761 nip = nashtable[kent];
762 while(nip && nip != rip) {pip = nip; nip = nip->Next;}
763
764// Remove if found
765//
766 if (nip)
767 {if (pip) pip->Next = nip->Next;
768 else nashtable[kent] = nip->Next;
769 nashnum--;
770 }
771 return nip != 0;
772}
773
774/******************************************************************************/
775/* C l a s s X r d O f s H a n x p r */
776/******************************************************************************/
777/******************************************************************************/
778/* a d d 2 Q */
779/******************************************************************************/
780
782{
783 XrdOfsHanXpr *xPP, *xP;
784
785// Place this object on the deferred queue
786//
787 if (doLK) xqCV.Lock();
788 xPP = 0; xP = xprQ;
789
790 while(xP && xP->xTime < xTime) {xPP = xP; xP = xP->Next;}
791
792 Next = xP;
793 if (xPP) {xPP->Next = this; if (doLK) xqCV.UnLock();}
794 else { xprQ = this; if (doLK) {xqCV.Signal(); xqCV.UnLock();}}
795};
796
797/******************************************************************************/
798/* public G e t */
799/******************************************************************************/
800
802{
803 XrdOfsHanXpr *xP;
804 XrdOfsHandle *hP;
805 int waitTime = 2592000;
806
807// Obtain the xqCV lock as we need it to inspect/modify the queue and elements
808// This lock is automatically released when we wait on the associated condvar.
809//
810 xqCV.Lock();
811
812// Caculate the next wait time based on the first element, if any, in the queue.
813// If the wait time is positive then loop back to wait that amount of time. Note
814// that we have the xqCV lock that is needed to touch an inq Xpr object.
815//
816do{do{if (!(xP = xprQ)) waitTime = 2592000;
817 else waitTime = xP->xTime - time(0);
818 if (waitTime > 0) break;
819 xprQ = xP->Next;
820
821// Get the associated file handle. If none, simply delete the Xpr object.
822//
823 if (!(hP = xP->Handle)) {delete xP; continue;}
824
825// If a new wait time is indicated then reschedule this object
826//
827 if (xP->xTNew)
828 {xP->xTime = xP->xTNew; xP->xTNew = 0;
829 xP->add2Q(0);
830 continue;
831 }
832
833// Since we are still holding the xqCV lock we must get a conditional lock on
834// the handle. If we can't then reschedule this object for later.
835//
836 if (!(hP->WaitLock()))
837 {OfsEroute.Emsg("Retire", "defering retire of", hP->Path.Val);
838 xP->xTime = time(0)+30;
839 xP->add2Q(0);
840 continue;
841 }
842
843// Drop the xqCV lock prior to returning the Xpr object to the caller. The
844// caller will delete the object as needed.
845//
846 xqCV.UnLock();
847 return xP;
848
849 } while(1);
850
851// We have the xqCV lock so we can now wait for an event or a timeout
852//
853 xqCV.Wait(waitTime);
854 } while(1);
855}
struct stat Stat
Definition XrdCks.cc:49
void * XrdOfsHanXpire(void *pp)
XrdSysError OfsEroute
XrdSysError OfsEroute(0)
XrdOfsStats OfsStats
Definition XrdOfs.cc:113
#define stat(a, b)
Definition XrdPosix.hh:101
int Mode
struct myOpts opts
size_t strlcpy(char *dst, const char *src, size_t sz)
virtual void Retired(XrdOfsHandle *)=0
unsigned int Links
unsigned int Hash
const char * Val
XrdOfsHanOssErr(XrdOssDF *ossp, int rrc=-EBADF, int wrc=-EBADF)
ssize_t ReadV(XrdOucIOVec *readV, int rdvcnt)
ssize_t Read(void *buff, off_t offset, size_t rlen)
int Readdir(char *buff, int blen)
int pgRead(XrdSfsAio *aioparm, uint64_t opts)
int Fstat(struct stat *Stat)
int Close(long long *retsz=0)
int Read(XrdSfsAio *aiop)
ssize_t pgRead(void *buffer, off_t offset, size_t rdlen, uint32_t *csvec, uint64_t opts)
ssize_t Read(off_t offset, size_t rlen)
ssize_t ReadRaw(void *buff, off_t offset, size_t rlen)
ssize_t ReadV(XrdOucIOVec *readV, int rdvcnt)
int Open(const char *, int, mode_t, XrdOucEnv &)
ssize_t pgRead(void *buffer, off_t offset, size_t rdlen, uint32_t *csvec, uint64_t opts)
int Fstat(struct stat *)
ssize_t ReadRaw(void *, off_t, size_t)
ssize_t pgWrite(void *buffer, off_t offset, size_t wrlen, uint32_t *csvec, uint64_t opts)
ssize_t WriteV(XrdOucIOVec *writeV, int wrvcnt)
int Fchmod(mode_t mode)
int Readdir(char *buff, int blen)
int isCompressed(char *cxidp=0)
int pgRead(XrdSfsAio *aioparm, uint64_t opts)
int Fsync(XrdSfsAio *aiop)
off_t getMmap(void **addr)
ssize_t Write(const void *, off_t, size_t)
int Read(XrdSfsAio *aiop)
int Close(long long *retsz=0)
ssize_t Read(void *, off_t, size_t)
ssize_t Read(off_t, size_t)
int Opendir(const char *, XrdOucEnv &)
int Write(XrdSfsAio *aiop)
int Ftruncate(unsigned long long)
int pgWrite(XrdSfsAio *aioparm, uint64_t opts)
XrdOfsHanOss(int rrc=-EBADF, int wrc=-EBADF)
static XrdOfsHanPsc * Alloc()
XrdOfsHanXpr * xprP
XrdOfsHandle * Find(XrdOfsHanKey &Key)
XrdOfsHanTab(int psize=987, int size=1597)
int Remove(XrdOfsHandle *rip)
void Add(XrdOfsHandle *hP)
static XrdOfsHanXpr * Get()
void Set(XrdOfsHanCB *cbP, time_t xtm)
XrdOfsHanXpr(XrdOfsHandle *hP, XrdOfsHanCB *cbP, time_t xtm)
friend class XrdOfsHandle
void add2Q(int doLK=1)
int Retire(int &retc, long long *retsz=0, char *buff=0, int blen=0)
static void Hide(const char *thePath)
int PoscSet(const char *User, int Unum, short Mode)
static const int opRW
int PoscGet(short &Mode, int Done=0)
static int StartXpr(int Init=0)
static const int opPC
friend class XrdOfsHanTab
void Suppress(int rrc=-EDOM, int wrc=-EDOM)
static int Alloc(const char *thePath, int Opts, XrdOfsHandle **Handle)
friend class XrdOfsHanXpr
const char * PoscUsr()
uint16_t dfType
Definition XrdOss.hh:456
const char * tident
Definition XrdOss.hh:453
virtual const char * getTID()
Definition XrdOss.hh:434
XrdOssDF(const char *tid="", uint16_t dftype=0, int fdnum=-1)
Definition XrdOss.hh:444
int fd
Definition XrdOss.hh:455
virtual int Close(long long *retsz=0)=0
virtual int getFD()
Definition XrdOss.hh:426
uint16_t DFType()
Definition XrdOss.hh:396
int TimedLock(int wait_ms)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)