XRootD
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 
36 #include "XrdOfs/XrdOfsHandle.hh"
37 #include "XrdOfs/XrdOfsStats.hh"
38 #include "XrdOss/XrdOss.hh"
39 #include "XrdSys/XrdSysError.hh"
40 #include "XrdSys/XrdSysPlatform.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 
50 class XrdOfsHanOss : public XrdOssDF
51 {
52 public:
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 
88 protected:
89 int rRC;
90 int wRC;
91 };
92 
93 /******************************************************************************/
94 /* X r d O f s H a n O s s E r r */
95 /******************************************************************************/
96 
98 {
99 public:
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 
150  ~XrdOfsHanOssErr() {delete ossP;}
151 
152 protected:
153 
155 };
156 
157 /******************************************************************************/
158 /* X r d O f s H a n X p r */
159 /******************************************************************************/
160 
162 {
163 friend class XrdOfsHandle;
164 public:
165 
166  void add2Q(int doLK=1);
167 
168  void Deref()
169  {xqCV.Lock(); Handle=0; Call=0; xTNew=0; xqCV.UnLock();}
170 
171 static 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 
180 private:
181  XrdOfsHanXpr *Next;
182  XrdOfsHandle *Handle;
183  XrdOfsHanCB *Call;
184  time_t xTime;
185  time_t xTNew;
186 
187 static XrdSysCondVar xqCV;
188 static XrdOfsHanXpr *xprQ;
189 };
190 
191 XrdSysCondVar XrdOfsHanXpr::xqCV(0, "HanXpr cv");
192 XrdOfsHanXpr *XrdOfsHanXpr::xprQ = 0;
193 
194 /******************************************************************************/
195 /* X r d O f s H a n P s c */
196 /******************************************************************************/
197 
199 {
200 public:
201 
202 union {
203 XrdOfsHanPsc *Next;
204 char *User; // -> Owner for posc files (user.pid:fd@host)
205  };
206 XrdOfsHanXpr *xprP; // -> Associate Xpr object if active
207 int Unum; // -> Offset in poscq
208 short Ulen; // Length of user.pid
209 short Uhst; // -> Host portion
210 short Mode; // Mode file is to have
211 
212 static
214 
215 void Recycle();
216 
217  XrdOfsHanPsc() : User(0), xprP(0), Unum(0), Ulen(0),
218  Uhst(0), Mode(0) {}
220 private:
221 
222 static XrdSysMutex pscMutex;
223 static XrdOfsHanPsc *Free;
224 };
225 
226 XrdSysMutex XrdOfsHanPsc::pscMutex;
227 XrdOfsHanPsc *XrdOfsHanPsc::Free = 0;
228 
229 /******************************************************************************/
230 /* E x t e r n a l L i n k a g e s */
231 /******************************************************************************/
232 
233 void *XrdOfsHanXpire(void *pp)
234 {
236  return (void *)0;
237 }
238 
239 extern XrdSysError OfsEroute;
240 
241 extern XrdOfsStats OfsStats;
242 
243 /******************************************************************************/
244 /* S t a t i c O b j e c t s */
245 /******************************************************************************/
246 
247 XrdSysMutex XrdOfsHandle::myMutex;
248 XrdOfsHanTab XrdOfsHandle::roTable;
249 XrdOfsHanTab XrdOfsHandle::rwTable;
250 XrdOssDF *XrdOfsHandle::ossDF = (XrdOssDF *)new XrdOfsHanOss;
251 XrdOfsHandle *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 
260 int 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);
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 
313 int 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 
346 void 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 
366 int 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 
392 int 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 
458 int 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 
489 int XrdOfsHandle::Retire(XrdOfsHanCB *cbP, int hTime)
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 //
546 do{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 
583 void 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 
592 int 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 
651 XrdOfsHanTab::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 
685 void 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 
781 void XrdOfsHanXpr::add2Q(int doLK)
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 //
816 do{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
XrdOfsStats OfsStats
Definition: XrdOfs.cc:113
XrdSysError OfsEroute
void * XrdOfsHanXpire(void *pp)
int stat(const char *path, struct stat *buf)
int Mode
struct myOpts opts
if(Avsz)
size_t strlcpy(char *dst, const char *src, size_t sz)
virtual void Retired(XrdOfsHandle *)=0
unsigned int Links
Definition: XrdOfsHandle.hh:51
unsigned int Hash
Definition: XrdOfsHandle.hh:52
const char * Val
Definition: XrdOfsHandle.hh:50
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)
XrdOssDF * ossP
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)
Definition: XrdOfsHandle.cc:75
int Open(const char *, int, mode_t, XrdOucEnv &)
Definition: XrdOfsHandle.cc:65
ssize_t pgRead(void *buffer, off_t offset, size_t rdlen, uint32_t *csvec, uint64_t opts)
Definition: XrdOfsHandle.cc:66
int Fstat(struct stat *)
Definition: XrdOfsHandle.cc:59
ssize_t ReadRaw(void *, off_t, size_t)
Definition: XrdOfsHandle.cc:76
ssize_t pgWrite(void *buffer, off_t offset, size_t wrlen, uint32_t *csvec, uint64_t opts)
Definition: XrdOfsHandle.cc:69
ssize_t WriteV(XrdOucIOVec *writeV, int wrvcnt)
Definition: XrdOfsHandle.cc:79
int Fchmod(mode_t mode)
Definition: XrdOfsHandle.cc:58
int Readdir(char *buff, int blen)
Definition: XrdOfsHandle.cc:55
int isCompressed(char *cxidp=0)
Definition: XrdOfsHandle.cc:64
int pgRead(XrdSfsAio *aioparm, uint64_t opts)
Definition: XrdOfsHandle.cc:68
int Fsync(XrdSfsAio *aiop)
Definition: XrdOfsHandle.cc:61
off_t getMmap(void **addr)
Definition: XrdOfsHandle.cc:63
ssize_t Write(const void *, off_t, size_t)
Definition: XrdOfsHandle.cc:77
int Read(XrdSfsAio *aiop)
Definition: XrdOfsHandle.cc:74
int Close(long long *retsz=0)
Definition: XrdOfsHandle.cc:82
ssize_t Read(void *, off_t, size_t)
Definition: XrdOfsHandle.cc:73
ssize_t Read(off_t, size_t)
Definition: XrdOfsHandle.cc:72
int Opendir(const char *, XrdOucEnv &)
Definition: XrdOfsHandle.cc:54
int Write(XrdSfsAio *aiop)
Definition: XrdOfsHandle.cc:78
int Ftruncate(unsigned long long)
Definition: XrdOfsHandle.cc:62
int pgWrite(XrdSfsAio *aioparm, uint64_t opts)
Definition: XrdOfsHandle.cc:71
XrdOfsHanOss(int rrc=-EBADF, int wrc=-EBADF)
Definition: XrdOfsHandle.cc:84
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)
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
void Suppress(int rrc=-EDOM, int wrc=-EDOM)
static int Alloc(const char *thePath, int Opts, XrdOfsHandle **Handle)
friend class XrdOfsHanXpr
const char * PoscUsr()
struct XrdOfsStats::StatsData Data
void Dec(int &Cntr)
Definition: XrdOfsStats.hh:64
void Add(int &Cntr)
Definition: XrdOfsStats.hh:62
uint16_t dfType
Definition: XrdOss.hh:456
const char * tident
Definition: XrdOss.hh:453
virtual const char * getTID()
Definition: XrdOss.hh:434
int fd
Definition: XrdOss.hh:455
virtual int Readdir(char *buff, int blen)
Definition: XrdOss.hh:92
virtual int Fstat(struct stat *buf)
Definition: XrdOss.hh:136
virtual ssize_t ReadRaw(void *buffer, off_t offset, size_t size)
Definition: XrdOss.hh:319
virtual int Close(long long *retsz=0)=0
virtual int getFD()
Definition: XrdOss.hh:426
virtual ssize_t Read(off_t offset, size_t size)
Definition: XrdOss.hh:281
virtual ssize_t pgRead(void *buffer, off_t offset, size_t rdlen, uint32_t *csvec, uint64_t opts)
Definition: XrdOss.cc:160
virtual ssize_t ReadV(XrdOucIOVec *readV, int rdvcnt)
Definition: XrdOss.cc:236
uint16_t DFType()
Definition: XrdOss.hh:396
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
int TimedLock(int wait_ms)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
int Opts
Definition: XrdMpxStats.cc:58