/******************************************************************************/ /* */ /* X r d C m s C l i e n t M s g . c c */ /* */ /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include "XProtocol/YProtocol.hh" #include "XrdCms/XrdCmsClientMsg.hh" #include "XrdCms/XrdCmsParser.hh" #include "XrdCms/XrdCmsTrace.hh" #include "XrdOuc/XrdOucBuffer.hh" #include "XrdOuc/XrdOucErrInfo.hh" using namespace XrdCms; /******************************************************************************/ /* G l o b a l s */ /******************************************************************************/ int XrdCmsClientMsg::nextid = 0; int XrdCmsClientMsg::numinQ = 0; XrdCmsClientMsg *XrdCmsClientMsg::msgTab = 0; XrdCmsClientMsg *XrdCmsClientMsg::nextfree = 0; XrdSysMutex XrdCmsClientMsg::FreeMsgQ; /******************************************************************************/ /* A l l o c */ /******************************************************************************/ // Returns the message object locked! XrdCmsClientMsg *XrdCmsClientMsg::Alloc(XrdOucErrInfo *erp) { XrdCmsClientMsg *mp; int lclid; // Allocate a message object // FreeMsgQ.Lock(); if (nextfree) {mp = nextfree; nextfree = mp->next;} else {FreeMsgQ.UnLock(); return (XrdCmsClientMsg *)0;} lclid = nextid = (nextid + MidIncr) & IncMask; numinQ++; FreeMsgQ.UnLock(); // Initialize it // mp->Hold.Lock(); mp->id = (mp->id & MidMask) | lclid; mp->Resp = erp; mp->next = 0; mp->inwaitq = 1; // Return the message object // return mp; } /******************************************************************************/ /* I n i t */ /******************************************************************************/ int XrdCmsClientMsg::Init() { int i; XrdCmsClientMsg *msgp; // Allocate the fixed number of msg blocks. These will never be freed! // if (!(msgp = new XrdCmsClientMsg[MaxMsgs]())) return 1; msgTab = &msgp[0]; nextid = MaxMsgs; // Place all of the msg blocks on the free list // for (i = 0; i < MaxMsgs; i++) {msgp->next = nextfree; nextfree = msgp; msgp->id = i; msgp++;} // All done // return 0; } /******************************************************************************/ /* R e c y c l e */ /******************************************************************************/ // Message object lock *must* be held by the caller upon entry! void XrdCmsClientMsg::Recycle() { static XrdOucErrInfo dummyResp; // Remove this from he wait queue and substitute a safe resp object. We do // this because a reply may be pending and will post when we release the lock // inwaitq = 0; Resp = &dummyResp; Hold.UnLock(); // Place message object on re-usable queue // FreeMsgQ.Lock(); next = nextfree; nextfree = this; if (numinQ >= 0) numinQ--; FreeMsgQ.UnLock(); } /******************************************************************************/ /* R e p l y */ /******************************************************************************/ int XrdCmsClientMsg::Reply(const char *Man, CmsRRHdr &hdr, XrdOucBuffer *buff) { EPNAME("Reply") XrdCmsClientMsg *mp; // Find the appropriate message // if (!(mp = XrdCmsClientMsg::RemFromWaitQ(hdr.streamid))) {DEBUG("to non-existent message; id=" <Result = XrdCmsParser::Decode(Man,hdr,buff,(XrdOucErrInfo *)(mp->Resp)); // Signal a reply and return // mp->Hold.Signal(); mp->Hold.UnLock(); return 1; } /******************************************************************************/ /* P r i v a t e M e t h o d s */ /******************************************************************************/ /******************************************************************************/ /* R e m F r o m W a i t Q */ /******************************************************************************/ // RemFromWaitQ() returns the msg object with the object locked! The caller // must unlock the object. XrdCmsClientMsg *XrdCmsClientMsg::RemFromWaitQ(int msgid) { int msgnum; // Locate the message object (the low order bits index it) // msgnum = msgid & MidMask; msgTab[msgnum].Hold.Lock(); if (!msgTab[msgnum].inwaitq || msgTab[msgnum].id != msgid) {msgTab[msgnum].Hold.UnLock(); return (XrdCmsClientMsg *)0;} msgTab[msgnum].inwaitq = 0; return &msgTab[msgnum]; }