XrdOfsHandle.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                       X r d O f s H a n d l e . c c                        */
00004 /*                                                                            */
00005 /* (c) 2008 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdOfsHandle.cc 29874 2009-08-21 16:56:04Z ganis $
00012 
00013 const char *XrdOfsHandleCVSID = "$Id: XrdOfsHandle.cc 29874 2009-08-21 16:56:04Z ganis $";
00014 
00015 #include <stdio.h>
00016 #include <time.h>
00017 #include <sys/errno.h>
00018 #include <sys/types.h>
00019 
00020 #include "XrdOfs/XrdOfsHandle.hh"
00021 #include "XrdOfs/XrdOfsStats.hh"
00022 #include "XrdOss/XrdOss.hh"
00023 #include "XrdSys/XrdSysError.hh"
00024 #include "XrdSys/XrdSysPlatform.hh"
00025 #include "XrdSys/XrdSysTimer.hh"
00026 
00027 /******************************************************************************/
00028 /*                         L o c a l   C l a s s e s                          */
00029 /******************************************************************************/
00030 /******************************************************************************/
00031 /*                          X r d O f s H a n O s s                           */
00032 /******************************************************************************/
00033 
00034 class XrdOfsHanOss : public XrdOssDF
00035 {
00036 public:
00037                 // Directory oriented methods
00038         int     Opendir(const char *)                        {return -EBADF;}
00039         int     Readdir(char *buff, int blen)                {return -EBADF;}
00040 
00041                 // File oriented methods
00042         int     Fstat(struct stat *)                         {return -EBADF;}
00043         int     Fsync()                                      {return -EBADF;}
00044         int     Fsync(XrdSfsAio *aiop)                       {return -EBADF;}
00045         int     Ftruncate(unsigned long long)                {return -EBADF;}
00046         off_t   getMmap(void **addr)                         {return 0;}
00047         int     isCompressed(char *cxidp=0)                  {return 0;}
00048         int     Open(const char *, int, mode_t, XrdOucEnv &) {return -EBADF;}
00049         ssize_t Read(off_t, size_t)                 {return (ssize_t)-EBADF;}
00050         ssize_t Read(void *, off_t, size_t)         {return (ssize_t)-EBADF;}
00051         int     Read(XrdSfsAio *aoip)               {return (ssize_t)-EBADF;}
00052         ssize_t ReadRaw(    void *, off_t, size_t)  {return (ssize_t)-EBADF;}
00053         ssize_t Write(const void *, off_t, size_t)  {return (ssize_t)-EBADF;}
00054         int     Write(XrdSfsAio *aiop)              {return (ssize_t)-EBADF;}
00055 
00056                 // Methods common to both
00057         int     Close(long long *retsz=0)                    {return -EBADF;}
00058 inline  int     Handle() {return -1;}
00059 
00060                 XrdOfsHanOss() {}
00061                ~XrdOfsHanOss() {}
00062 
00063 };
00064 
00065 /******************************************************************************/
00066 /*                          X r d O f s H a n X p r                           */
00067 /******************************************************************************/
00068   
00069 class XrdOfsHanXpr
00070 {
00071 friend class XrdOfsHandle;
00072 public:
00073 
00074        void          add2Q(int doLK=1);
00075 
00076        void          Deref()
00077                         {xqCV.Lock(); Handle=0; Call=0; xTNew=0; xqCV.UnLock();}
00078 
00079 static XrdOfsHanXpr *Get();
00080 
00081        void          Set(XrdOfsHanCB *cbP, time_t xtm)
00082                         {xqCV.Lock(); Call = cbP; xTNew = xtm; xqCV.UnLock();}
00083 
00084        XrdOfsHanXpr(XrdOfsHandle *hP, XrdOfsHanCB *cbP, time_t xtm)
00085                    : Next(0), Handle(hP), Call(cbP), xTime(xtm), xTNew(0) {}
00086       ~XrdOfsHanXpr() {}
00087 
00088 private:
00089        XrdOfsHanXpr *Next;
00090        XrdOfsHandle *Handle;
00091        XrdOfsHanCB  *Call;
00092        time_t        xTime;
00093        time_t        xTNew;
00094 
00095 static XrdSysCondVar xqCV;
00096 static XrdOfsHanXpr *xprQ;
00097 };
00098 
00099 XrdSysCondVar  XrdOfsHanXpr::xqCV(0, "HanXpr cv");
00100 XrdOfsHanXpr  *XrdOfsHanXpr::xprQ = 0;
00101 
00102 /******************************************************************************/
00103 /*                          X r d O f s H a n P s c                           */
00104 /******************************************************************************/
00105   
00106 class XrdOfsHanPsc
00107 {
00108 public:
00109 
00110 union {
00111 XrdOfsHanPsc  *Next;
00112 char          *User;   // -> Owner for posc files (user.pid:fd@host)
00113       };
00114 XrdOfsHanXpr  *xprP;   // -> Associate Xpr object if active
00115 int            Unum;   // -> Offset in poscq
00116 short          Ulen;   //    Length of user.pid
00117 short          Uhst;   // -> Host portion
00118 short          Mode;   //    Mode file is to have
00119 
00120 static
00121 XrdOfsHanPsc  *Alloc();
00122 
00123 void           Recycle();
00124 
00125                XrdOfsHanPsc() : User(0), xprP(0), Unum(0), Ulen(0),
00126                                 Uhst(0), Mode(0)  {}
00127               ~XrdOfsHanPsc() {}
00128 private:
00129 
00130 static XrdSysMutex    pscMutex;
00131 static XrdOfsHanPsc  *Free;
00132 };
00133 
00134 XrdSysMutex    XrdOfsHanPsc::pscMutex;
00135 XrdOfsHanPsc  *XrdOfsHanPsc::Free = 0;
00136 
00137 /******************************************************************************/
00138 /*                     E x t e r n a l   L i n k a g e s                      */
00139 /******************************************************************************/
00140   
00141 void *XrdOfsHanXpire(void *pp)
00142 {
00143      XrdOfsHandle::StartXpr();
00144      return (void *)0;
00145 }
00146 
00147 extern XrdSysError OfsEroute;
00148 
00149 extern XrdOfsStats OfsStats;
00150 
00151 /******************************************************************************/
00152 /*                        S t a t i c   O b j e c t s                         */
00153 /******************************************************************************/
00154   
00155 XrdSysMutex   XrdOfsHandle::myMutex;
00156 XrdOfsHanTab  XrdOfsHandle::roTable;
00157 XrdOfsHanTab  XrdOfsHandle::rwTable;
00158 XrdOssDF     *XrdOfsHandle::ossDF = (XrdOssDF *)new XrdOfsHanOss;
00159 XrdOfsHandle *XrdOfsHandle::Free = 0;
00160 
00161 /******************************************************************************/
00162 /*                    c l a s s   X r d O f s H a n d l e                     */
00163 /******************************************************************************/
00164 /******************************************************************************/
00165 /* static public                A l l o c   # 1                               */
00166 /******************************************************************************/
00167   
00168 int XrdOfsHandle::Alloc(const char *thePath, int Opts, XrdOfsHandle **Handle)
00169 {
00170    XrdOfsHandle *hP;
00171    XrdOfsHanTab *theTable = (Opts & opRW ? &rwTable : &roTable);
00172    XrdOfsHanKey theKey(thePath, (int)strlen(thePath));
00173    int          retc;
00174 
00175 // Lock the search table and try to find the key. If found, increment the
00176 // the link count (can only be done with the global lock) then release the
00177 // lock and try to lock the handle. It can't escape between lock calls because
00178 // the link count is positive. If we can't lock the handle then it must be the
00179 // that a long running operation is occuring. Return the handle to its former
00180 // state and return a delay. Otherwise, return the handle.
00181 //
00182    myMutex.Lock();
00183    if ((hP = theTable->Find(theKey)) && hP->Path.Links != 0xffff)
00184       {hP->Path.Links++; myMutex.UnLock();
00185        if (hP->WaitLock()) {*Handle = hP; return 0;}
00186        myMutex.Lock(); hP->Path.Links--; myMutex.UnLock();
00187        return nolokDelay;
00188       }
00189 
00190 // Get a new handle
00191 //
00192    if (!(retc = Alloc(theKey, Opts, Handle))) theTable->Add(*Handle);
00193    OfsStats.Add(OfsStats.Data.numHandles);
00194 
00195 // All done
00196 //
00197    myMutex.UnLock();
00198    return retc;
00199 }
00200 
00201 /******************************************************************************/
00202 /* static public                A l l o c   # 2                               */
00203 /******************************************************************************/
00204 
00205 int XrdOfsHandle::Alloc(XrdOfsHandle **Handle)
00206 {
00207     XrdOfsHanKey myKey("dummy", 5);
00208     int retc;
00209 
00210     myMutex.Lock();
00211     if (!(retc = Alloc(myKey, 0, Handle))) 
00212        {(*Handle)->Path.Links = 0; (*Handle)->UnLock();}
00213     myMutex.UnLock();
00214     return retc;
00215 }
00216 
00217 /******************************************************************************/
00218 /* private                      A l l o c   # 3                               */
00219 /******************************************************************************/
00220   
00221 int XrdOfsHandle::Alloc(XrdOfsHanKey theKey, int Opts, XrdOfsHandle **Handle)
00222 {
00223    static const int minAlloc = 4096/sizeof(XrdOfsHandle);
00224    XrdOfsHandle *hP;
00225 
00226 // No handle currently in the table. Get a new one off the free list
00227 //
00228    if (!Free && (hP = new XrdOfsHandle[minAlloc]))
00229       {int i = minAlloc; while(i--) {hP->Next = Free; Free = hP; hP++;}}
00230    if ((hP = Free)) Free = hP->Next;
00231 
00232 // Initialize the new handle, if we have one, and add it to the table
00233 //
00234    if (hP)
00235       {hP->Path         = theKey;
00236        hP->Path.Links   = 1;
00237        hP->isChanged    = 0;                       // File changed
00238        hP->isCompressed = 0;                       // Compression
00239        hP->isPending    = 0;                       // Pending output
00240        hP->isRW         = (Opts & opPC);           // File mode
00241        hP->ssi          = ossDF;                   // No storage system yet
00242        hP->Posc         = 0;                       // No creator
00243        hP->Lock();                                 // Wait is not possible
00244        *Handle = hP;
00245        return 0;
00246       }
00247    return nomemDelay;                              // Delay client
00248 }
00249   
00250 /******************************************************************************/
00251 /* static public                    H i d e                                   */
00252 /******************************************************************************/
00253 
00254 void XrdOfsHandle::Hide(const char *thePath)
00255 {
00256    XrdOfsHandle *hP;
00257    XrdOfsHanKey theKey(thePath, (int)strlen(thePath));
00258 
00259 // Lock the search table and try to find the key in each table. If found,
00260 // clear the length field to effectively hide the item.
00261 //
00262    myMutex.Lock();
00263    if ((hP = roTable.Find(theKey))) hP->Path.Len = 0;
00264    if ((hP = rwTable.Find(theKey))) hP->Path.Len = 0;
00265    myMutex.UnLock();
00266 }
00267 
00268 /******************************************************************************/
00269 /* public                        P o s c G e t                                */
00270 /******************************************************************************/
00271   
00272 // Warning: the handle must be locked!
00273 
00274 int XrdOfsHandle::PoscGet(short &Mode, int Done)
00275 {
00276    XrdOfsHanPsc *pP;
00277    int pnum;
00278 
00279    if (Posc)
00280       {pnum = Posc->Unum;
00281        Mode = Posc->Mode;
00282        if (Done)
00283           {pP = Posc; Posc = 0;
00284            if (pP->xprP) {myMutex.Lock(); Path.Links--; myMutex.UnLock();}
00285            pP->Recycle();
00286           }
00287        return pnum;
00288       }
00289 
00290    Mode = 0;
00291    return 0;
00292 }
00293   
00294 /******************************************************************************/
00295 /* public                        P o s c S e t                                */
00296 /******************************************************************************/
00297   
00298 // Warning: the handle must be locked!
00299 
00300 int XrdOfsHandle::PoscSet(const char *User, int Unum, short Umod)
00301 {
00302    static const char *Who = "?:0.0@?", *Whc = Who+1, *Whh = Who+5;
00303    const char *Col, *At;
00304    int retval = 0;
00305 
00306 // If we have no posc object then we may just be able to return
00307 //
00308    if (!Posc)
00309       {if (Unum > 0) Posc = XrdOfsHanPsc::Alloc();
00310           else return 0;
00311       }
00312 
00313 // Find the markers in the incomming user
00314 //
00315    if (!(Col = index(User, ':')) || !(At = index(User, '@')))
00316       {User = Who; Col = Whc; At = Whh;}
00317 
00318 // If we already have a user check if it matches
00319 //
00320    if (Posc->User)
00321       {if (!Unum)
00322           {if (!strncmp(User, Posc->User, Posc->Ulen)
00323            &&  !strcmp(Posc->User + Posc->Uhst, At+1)) return 0;
00324            return -ETXTBSY;
00325           } else {
00326            char buff[1024];
00327            sprintf(buff, "%s to %s for", Posc->User, User);
00328            OfsEroute.Emsg("Posc", "Creator changed from", buff, Path.Val);
00329            if (Unum < 0) Unum = Posc->Unum;
00330               else if (Unum !=  Posc->Unum) retval = Posc->Unum;
00331           }
00332        free(Posc->User);
00333       }
00334 
00335 // Assign creation values
00336 //
00337    Posc->User = strdup(User);
00338    Posc->Ulen = Col - User + 1;
00339    Posc->Uhst = At  - User + 1;
00340    Posc->Unum = Unum;
00341    Posc->Mode = Umod;
00342    return retval;
00343 }
00344   
00345 /******************************************************************************/
00346 /* public                        P o s c U s r                                */
00347 /******************************************************************************/
00348   
00349 // Warning: the handle must be locked!
00350 
00351 const char *XrdOfsHandle::PoscUsr()
00352 {
00353    if (Posc) return Posc->User;
00354    return "?@?";
00355 }
00356   
00357 /******************************************************************************/
00358 /* public                         R e t i r e                                 */
00359 /******************************************************************************/
00360 
00361 // The handle must be locked upon entry! It is unlocked upon exit.
00362 
00363 int XrdOfsHandle::Retire(long long *retsz, char *buff, int blen)
00364 {
00365    int numLeft;
00366 
00367 // Get the global lock as the links field can only be manipulated with it.
00368 // Decrement the links count and if zero, remove it from the table and
00369 // place it on the free list. Otherwise, it is still in use.
00370 //
00371    myMutex.Lock();
00372    if (Path.Links == 1)
00373       {if (buff) strlcpy(buff, Path.Val, blen);
00374        numLeft = 0; OfsStats.Dec(OfsStats.Data.numHandles);
00375        if ( (isRW ? rwTable.Remove(this) : roTable.Remove(this)) )
00376          {Next = Free; Free = this;
00377           if (Posc) {Posc->Recycle(); Posc = 0;}
00378           if (Path.Val) {free((void *)Path.Val); Path.Val = (char *)"";}
00379           Path.Len = 0;
00380           if (ssi && ssi != ossDF)
00381              {ssi->Close(retsz); delete ssi; ssi = ossDF;}
00382          } else OfsEroute.Emsg("Retire", "Lost handle to", Path.Val);
00383       } else numLeft = --Path.Links;
00384    UnLock();
00385    myMutex.UnLock();
00386    return numLeft;
00387 }
00388 
00389 /******************************************************************************/
00390 
00391 int XrdOfsHandle::Retire(XrdOfsHanCB *cbP, int hTime)
00392 {
00393    static int allOK = StartXpr(1);
00394    XrdOfsHanXpr *xP;
00395 
00396 // The handle can only be held by one reference and only if it's a POSC and
00397 // defered handling was properly set up.
00398 //
00399    myMutex.Lock();
00400    if (!Posc || !allOK)
00401       {OfsEroute.Emsg("Retire", "ignoring deferred retire of", Path.Val);
00402        if (Path.Links != 1 || !Posc || !cbP) myMutex.UnLock();
00403           else {myMutex.UnLock(); cbP->Retired(this);}
00404        return Retire();
00405       }
00406    myMutex.UnLock();
00407 
00408 // If this object already has an xpr object (happens for bouncing connections)
00409 // then reuse that object. Otherwise create a new one and put it on the queue.
00410 //
00411    if (Posc->xprP) Posc->xprP->Set(cbP, hTime+time(0));
00412       else {xP = Posc->xprP = new XrdOfsHanXpr(this, cbP, hTime+time(0));
00413             xP->add2Q();
00414            }
00415    UnLock();
00416    return 0;
00417 }
00418 
00419 /******************************************************************************/
00420 /* public                       S t a r t X p r                               */
00421 /******************************************************************************/
00422   
00423 int XrdOfsHandle::StartXpr(int Init)
00424 {
00425    static int InitDone = 0;
00426    XrdOfsHanXpr *xP;
00427    XrdOfsHandle *hP;
00428 
00429 // If this is the initial all and we have not been initialized do so
00430 //
00431    if (Init)
00432       {pthread_t tid;
00433        int rc;
00434        if (InitDone) return InitDone == 1;
00435        if ((rc = XrdSysThread::Run(&tid, XrdOfsHanXpire, (void *)0,
00436                                    0, "Handle Timeout")))
00437           {OfsEroute.Emsg("StartXpr", rc, "create handle timeout thread");
00438            InitDone = -1; return 0;
00439           }
00440        InitDone = 1; return 1;
00441       }
00442 
00443 // Simply loop waiting for expired handles to become available. The Get() will
00444 // return an Xpr object with the associated handle locked. 
00445 //
00446 do{xP = XrdOfsHanXpr::Get(); hP = xP->Handle;
00447 
00448 // Perform validity check on the handle to catch instances where the handle
00449 // was closed while we were in the process of getting it. While this is safe
00450 // it should never happen, so issue a message so we know to fix it.
00451 //
00452    if (hP->Posc && xP == hP->Posc->xprP) hP->Posc->xprP = 0;
00453       else {OfsEroute.Emsg("StarXtpr", "Invalid xpr ref to", hP->Path.Val);
00454             hP->UnLock(); delete xP; continue;
00455            }
00456 
00457 // As the handle is locked we can get the global handle lock to prevent
00458 // additions and removals of handles as we need a stable reference count to
00459 // effect the callout, if any. Do so only if the reference count is one (for us)
00460 // and the handle is active. In all cases, drop the global lock.
00461 //
00462    myMutex.Lock();
00463    if (hP->Path.Links != 1 || !xP->Call) myMutex.UnLock();
00464       else {myMutex.UnLock();
00465             xP->Call->Retired(hP);
00466            }
00467 
00468 // We can now officially retire the handle and delete the xpr object
00469 //
00470    hP->Retire();
00471    delete xP;
00472   } while(1);
00473 
00474 // Keep the compiler happy
00475 //
00476    return 0;
00477 }
00478 
00479 /******************************************************************************/
00480 /* public                       W a i t L o c k                               */
00481 /******************************************************************************/
00482   
00483 int XrdOfsHandle::WaitLock(void)
00484 {
00485    int ntry = LockTries;
00486 
00487 // Try to obtain a lock within the retry parameters
00488 //
00489    while(ntry--)
00490         {if (hMutex.CondLock()) return 1;
00491          if (ntry) XrdSysTimer::Wait(LockWait);
00492         }
00493 
00494 // Indicate we could not get a lock
00495 //
00496    return 0;
00497 }
00498 
00499 /******************************************************************************/
00500 /*                    C l a s s   X r d O f s H a n P s c                     */
00501 /******************************************************************************/
00502 /******************************************************************************/
00503 /*                                 A l l o c                                  */
00504 /******************************************************************************/
00505   
00506 XrdOfsHanPsc *XrdOfsHanPsc::Alloc()
00507 {
00508    XrdOfsHanPsc *pP;
00509 
00510 // Grab or allocate an object
00511 //
00512    pscMutex.Lock();
00513    if ((pP = Free)) {Free = pP->Next; pP->Next = 0;}
00514       else pP = new XrdOfsHanPsc;
00515    pscMutex.UnLock();
00516 
00517    return pP;
00518 }
00519 
00520 /******************************************************************************/
00521 /*                               R e c y c l e                                */
00522 /******************************************************************************/
00523   
00524 void XrdOfsHanPsc::Recycle()
00525 {
00526 
00527 // Release any storgae appendages and clear other field
00528 //
00529    if (xprP) {xprP->Deref(); xprP = 0;}
00530    if (User) free(User);
00531    Unum = 0;
00532    Ulen = 0;
00533    Uhst = 0;
00534    Mode = 0;
00535 
00536 // Place element on free chain. We keep them all as there are never too many
00537 //
00538    pscMutex.Lock();
00539    Next = Free; Free = this;
00540    pscMutex.UnLock();
00541 }
00542 
00543 /******************************************************************************/
00544 /*                    C l a s s   X r d O f s H a n T a b                     */
00545 /******************************************************************************/
00546 /******************************************************************************/
00547 /*                           C o n s t r u c t o r                            */
00548 /******************************************************************************/
00549   
00550 XrdOfsHanTab::XrdOfsHanTab(int psize, int csize)
00551 {
00552      prevtablesize = psize;
00553      nashtablesize = csize;
00554      Threshold     = (csize * LoadMax) / 100;
00555      nashnum       = 0;
00556      nashtable     = (XrdOfsHandle **)
00557                      malloc( (size_t)(csize*sizeof(XrdOfsHandle *)) );
00558      memset((void *)nashtable, 0, (size_t)(csize*sizeof(XrdOfsHandle *)));
00559 }
00560 
00561 /******************************************************************************/
00562 /* public                            A d d                                    */
00563 /******************************************************************************/
00564   
00565 void XrdOfsHanTab::Add(XrdOfsHandle *hip)
00566 {
00567    unsigned int kent;
00568 
00569 // Check if we should expand the table
00570 //
00571    if (++nashnum > Threshold) Expand();
00572 
00573 // Add the entry to the table
00574 //
00575    kent = hip->Path.Hash % nashtablesize;
00576    hip->Next = nashtable[kent];
00577    nashtable[kent] = hip;
00578 }
00579   
00580 /******************************************************************************/
00581 /* private                        E x p a n d                                 */
00582 /******************************************************************************/
00583   
00584 void XrdOfsHanTab::Expand()
00585 {
00586    int newsize, newent, i;
00587    size_t memlen;
00588    XrdOfsHandle **newtab, *nip, *nextnip;
00589 
00590 // Compute new size for table using a fibonacci series
00591 //
00592    newsize = prevtablesize + nashtablesize;
00593 
00594 // Allocate the new table
00595 //
00596    memlen = (size_t)(newsize*sizeof(XrdOfsHandle *));
00597    if (!(newtab = (XrdOfsHandle **) malloc(memlen))) return;
00598    memset((void *)newtab, 0, memlen);
00599 
00600 // Redistribute all of the current items
00601 //
00602    for (i = 0; i < nashtablesize; i++)
00603        {nip = nashtable[i];
00604         while(nip)
00605              {nextnip = nip->Next;
00606               newent  = nip->Path.Hash % newsize;
00607               nip->Next = newtab[newent];
00608               newtab[newent] = nip;
00609               nip = nextnip;
00610              }
00611        }
00612 
00613 // Free the old table and plug in the new table
00614 //
00615    free((void *)nashtable);
00616    nashtable     = newtab;
00617    prevtablesize = nashtablesize;
00618    nashtablesize = newsize;
00619 
00620 // Compute new expansion threshold
00621 //
00622    Threshold = static_cast<int>((static_cast<long long>(newsize)*LoadMax)/100);
00623 }
00624 
00625 /******************************************************************************/
00626 /* public                           F i n d                                   */
00627 /******************************************************************************/
00628   
00629 XrdOfsHandle *XrdOfsHanTab::Find(XrdOfsHanKey &Key)
00630 {
00631   XrdOfsHandle *nip;
00632   unsigned int kent;
00633 
00634 // Compute position of the hash table entry
00635 //
00636    kent = Key.Hash%nashtablesize;
00637 
00638 // Find the entry
00639 //
00640    nip = nashtable[kent];
00641    while(nip && nip->Path != Key) nip = nip->Next;
00642    return nip;
00643 }
00644 
00645 /******************************************************************************/
00646 /* public                         R e m o v e                                 */
00647 /******************************************************************************/
00648   
00649 int XrdOfsHanTab::Remove(XrdOfsHandle *rip)
00650 {
00651    XrdOfsHandle *nip, *pip = 0;
00652    unsigned int kent;
00653 
00654 // Compute position of the hash table entry
00655 //
00656    kent = rip->Path.Hash%nashtablesize;
00657 
00658 // Find the entry
00659 //
00660    nip = nashtable[kent];
00661    while(nip && nip != rip) {pip = nip; nip = nip->Next;}
00662 
00663 // Remove if found
00664 //
00665    if (nip)
00666       {if (pip) pip->Next = nip->Next;
00667           else nashtable[kent] = nip->Next;
00668        nashnum--;
00669       }
00670    return nip != 0;
00671 }
00672 
00673 /******************************************************************************/
00674 /*                    C l a s s   X r d O f s H a n x p r                     */
00675 /******************************************************************************/
00676 /******************************************************************************/
00677 /*                                 a d d 2 Q                                  */
00678 /******************************************************************************/
00679 
00680 void XrdOfsHanXpr::add2Q(int doLK)
00681 {
00682    XrdOfsHanXpr *xPP, *xP;
00683 
00684 // Place this object on the defered queue
00685 //
00686    if (doLK) xqCV.Lock();
00687    xPP = 0; xP = xprQ;
00688 
00689    while(xP && xP->xTime < xTime) {xPP = xP; xP = xP->Next;}
00690 
00691    Next = xP;
00692    if (xPP) {xPP->Next = this; if (doLK)  xqCV.UnLock();}
00693       else  {     xprQ = this; if (doLK) {xqCV.Signal(); xqCV.UnLock();}}
00694 };
00695 
00696 /******************************************************************************/
00697 /* public                            G e t                                    */
00698 /******************************************************************************/
00699 
00700 XrdOfsHanXpr *XrdOfsHanXpr::Get()
00701 {
00702    XrdOfsHanXpr *xP;
00703    XrdOfsHandle *hP;
00704    int waitTime = 2592000;
00705 
00706 // Obtain the xqCV lock as we need it to inspect/modify the queue and elements
00707 // This lock is automatically released when we wait on the associated condvar.
00708 //
00709    xqCV.Lock();
00710 
00711 // Caculate the next wait time based on the first element, if any, in the queue.
00712 // If the wait time is positive then loop back to wait that amount of time. Note
00713 // that we have the xqCV lock that is needed to touch an inq Xpr object.
00714 //
00715 do{do{if (!(xP = xprQ)) waitTime = 2592000;
00716          else waitTime = xP->xTime - time(0);
00717       if (waitTime > 0) break;
00718       xprQ = xP->Next;
00719 
00720 // Get the associated file handle. If none, simply delete the Xpr object.
00721 //
00722       if (!(hP = xP->Handle)) {delete xP; continue;}
00723 
00724 // If a new wait time is indicated then reschedule this object
00725 //
00726       if (xP->xTNew)
00727          {xP->xTime = xP->xTNew; xP->xTNew = 0;
00728           xP->add2Q(0);
00729           continue;
00730          }
00731 
00732 // Since we are still holding the xqCV lock we must get a conditional lock on
00733 // the handle. If we can't then reschedule this object for later.
00734 //
00735       if (!(hP->WaitLock()))
00736          {OfsEroute.Emsg("Retire", "defering retire of", hP->Path.Val);
00737           xP->xTime = time(0)+30;
00738           xP->add2Q(0);
00739           continue;
00740          }
00741 
00742 // Drop the xqCV lock prior to returning the Xpr object to the caller. The
00743 // caller will delete the object as needed.
00744 //
00745    xqCV.UnLock();
00746    return xP;
00747 
00748      } while(1);
00749 
00750 // We have the xqCV lock so we can now wait for an event or a timeout
00751 //
00752    xqCV.Wait(waitTime);
00753   } while(1);
00754 }

Generated on Tue Jul 5 14:46:44 2011 for ROOT_528-00b_version by  doxygen 1.5.1