00001 /******************************************************************************/ 00002 /* */ 00003 /* X r d C m s C l i e n t M s g . c c */ 00004 /* */ 00005 /* (c) 2007 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-AC02-76-SFO0515 with the Department of Energy */ 00009 /******************************************************************************/ 00010 00011 // $Id: XrdCmsClientMsg.cc 38011 2011-02-08 18:35:57Z ganis $ 00012 00013 // Vased on: XrdCmsClientMsg.cc,v 1.14 2006/09/26 07:49:14 abh 00014 00015 const char *XrdCmsClientMsgCVSID = "$Id: XrdCmsClientMsg.cc 38011 2011-02-08 18:35:57Z ganis $"; 00016 00017 #include <stdlib.h> 00018 00019 #include "XProtocol/YProtocol.hh" 00020 #include "XrdCms/XrdCmsClientMsg.hh" 00021 #include "XrdCms/XrdCmsParser.hh" 00022 #include "XrdCms/XrdCmsTrace.hh" 00023 #include "XrdOuc/XrdOucErrInfo.hh" 00024 #include "XrdNet/XrdNetBuffer.hh" 00025 00026 using namespace XrdCms; 00027 00028 /******************************************************************************/ 00029 /* G l o b a l s */ 00030 /******************************************************************************/ 00031 00032 int XrdCmsClientMsg::nextid = 0; 00033 int XrdCmsClientMsg::numinQ = 0; 00034 00035 XrdCmsClientMsg *XrdCmsClientMsg::msgTab = 0; 00036 XrdCmsClientMsg *XrdCmsClientMsg::nextfree = 0; 00037 00038 XrdSysMutex XrdCmsClientMsg::FreeMsgQ; 00039 00040 /******************************************************************************/ 00041 /* A l l o c */ 00042 /******************************************************************************/ 00043 00044 // Returns the message object locked! 00045 00046 XrdCmsClientMsg *XrdCmsClientMsg::Alloc(XrdOucErrInfo *erp) 00047 { 00048 XrdCmsClientMsg *mp; 00049 int lclid; 00050 00051 // Allocate a message object 00052 // 00053 FreeMsgQ.Lock(); 00054 if (nextfree) {mp = nextfree; nextfree = mp->next;} 00055 else {FreeMsgQ.UnLock(); return (XrdCmsClientMsg *)0;} 00056 lclid = nextid = (nextid + MidIncr) & IncMask; 00057 numinQ++; 00058 FreeMsgQ.UnLock(); 00059 00060 // Initialize it 00061 // 00062 mp->Hold.Lock(); 00063 mp->id = (mp->id & MidMask) | lclid; 00064 mp->Resp = erp; 00065 mp->next = 0; 00066 mp->inwaitq = 1; 00067 00068 // Return the message object 00069 // 00070 return mp; 00071 } 00072 00073 /******************************************************************************/ 00074 /* I n i t */ 00075 /******************************************************************************/ 00076 00077 int XrdCmsClientMsg::Init() 00078 { 00079 int i; 00080 XrdCmsClientMsg *msgp; 00081 00082 // Allocate the fixed number of msg blocks. These will never be freed! 00083 // 00084 if (!(msgp = new XrdCmsClientMsg[MaxMsgs]())) return 1; 00085 msgTab = &msgp[0]; 00086 nextid = MaxMsgs; 00087 00088 // Place all of the msg blocks on the free list 00089 // 00090 for (i = 0; i < MaxMsgs; i++) 00091 {msgp->next = nextfree; nextfree = msgp; msgp->id = i; msgp++;} 00092 00093 // All done 00094 // 00095 return 0; 00096 } 00097 00098 /******************************************************************************/ 00099 /* R e c y c l e */ 00100 /******************************************************************************/ 00101 00102 // Message object lock *must* be held by the caller upon entry! 00103 00104 void XrdCmsClientMsg::Recycle() 00105 { 00106 static XrdOucErrInfo dummyResp; 00107 00108 // Remove this from he wait queue and substitute a safe resp object. We do 00109 // this because a reply may be pending and will post when we release the lock 00110 // 00111 inwaitq = 0; 00112 Resp = &dummyResp; 00113 Hold.UnLock(); 00114 00115 // Place message object on re-usable queue 00116 // 00117 FreeMsgQ.Lock(); 00118 next = nextfree; 00119 nextfree = this; 00120 if (numinQ >= 0) numinQ--; 00121 FreeMsgQ.UnLock(); 00122 } 00123 00124 /******************************************************************************/ 00125 /* R e p l y */ 00126 /******************************************************************************/ 00127 00128 int XrdCmsClientMsg::Reply(const char *Man, CmsRRHdr &hdr, XrdNetBuffer *buff) 00129 { 00130 EPNAME("Reply") 00131 XrdCmsClientMsg *mp; 00132 00133 // Find the appropriate message 00134 // 00135 if (!(mp = XrdCmsClientMsg::RemFromWaitQ(hdr.streamid))) 00136 {DEBUG("to non-existent message; id=" <<hdr.streamid); 00137 return 0; 00138 } 00139 00140 // Decode the response 00141 // 00142 mp->Result = XrdCmsParser::Decode(Man, hdr, buff->data, buff->dlen, 00143 (XrdOucErrInfo *)(mp->Resp)); 00144 00145 // Signal a reply and return 00146 // 00147 mp->Hold.Signal(); 00148 mp->Hold.UnLock(); 00149 return 1; 00150 } 00151 00152 /******************************************************************************/ 00153 /* P r i v a t e M e t h o d s */ 00154 /******************************************************************************/ 00155 /******************************************************************************/ 00156 /* R e m F r o m W a i t Q */ 00157 /******************************************************************************/ 00158 00159 // RemFromWaitQ() returns the msg object with the object locked! The caller 00160 // must unlock the object. 00161 00162 XrdCmsClientMsg *XrdCmsClientMsg::RemFromWaitQ(int msgid) 00163 { 00164 int msgnum; 00165 00166 // Locate the message object (the low order bits index it) 00167 // 00168 msgnum = msgid & MidMask; 00169 msgTab[msgnum].Hold.Lock(); 00170 if (!msgTab[msgnum].inwaitq || msgTab[msgnum].id != msgid) 00171 {msgTab[msgnum].Hold.UnLock(); return (XrdCmsClientMsg *)0;} 00172 msgTab[msgnum].inwaitq = 0; 00173 return &msgTab[msgnum]; 00174 }