XRootD
XrdSsiResponder.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S s i R e s p o n d e r . h h */
4 /* */
5 /* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include "XrdSsi/XrdSsiAtomics.hh"
32 #include "XrdSsi/XrdSsiRRAgent.hh"
33 
34 /******************************************************************************/
35 /* L o c a l D e f i n e s */
36 /******************************************************************************/
37 
38 #define SSI_VAL_RESPONSE spMutex.Lock();\
39  if (!reqP)\
40  {spMutex.UnLock(); return notActive;}\
41  reqP->rrMutex->Lock();\
42  if (reqP->theRespond != this)\
43  {reqP->rrMutex->UnLock(); spMutex.UnLock();\
44  return notActive;\
45  }\
46  if (reqP->Resp.rType)\
47  {reqP->rrMutex->UnLock(); spMutex.UnLock();\
48  return notPosted;\
49  }
50 
51 #define SSI_XEQ_RESPONSE if (reqP->onClient)\
52  {XrdSsiRequest *rX = reqP;\
53  reqP->rrMutex->UnLock(); spMutex.UnLock();\
54  return (rX->ProcessResponse(rX->errInfo,rX->Resp)\
55  ? wasPosted : notActive);\
56  } else {\
57  bool isOK = reqP->ProcessResponse(reqP->errInfo,\
58  reqP->Resp);\
59  reqP->rrMutex->UnLock(); spMutex.UnLock();\
60  return (isOK ? wasPosted : notActive);\
61  }
62 
63 /******************************************************************************/
64 /* L o c a l C l a s s e s */
65 /******************************************************************************/
66 
67 namespace
68 {
69 class XeqUnBind : public XrdSsiResponder
70 {
71 public:
72 
73 virtual void Finished( XrdSsiRequest &rqstR,
74  const XrdSsiRespInfo &rInfo,
75  bool cancel=false)
76  {XrdSsiRRAgent::Dispose(rqstR);}
77 
78  XeqUnBind() {}
79  ~XeqUnBind() {}
80 };
81 }
82 
83 /******************************************************************************/
84 /* S t a t i c s */
85 /******************************************************************************/
86 
87 namespace
88 {
89 XeqUnBind ForceUnBind;
90 }
91 
92 /******************************************************************************/
93 /* C o n s t r u c t o r */
94 /******************************************************************************/
95 
97  : spMutex(XrdSsiMutex::Recursive), reqP(0),
98  rsvd1(0), rsvd2(0), rsvd3(0)
99  {}
100 
101 /******************************************************************************/
102 /* D e s t r u c t o r */
103 /******************************************************************************/
104 
106 {
107 // Lock ourselves (unlikely that we need to).
108 //
109  spMutex.Lock();
110 
111 // If we haven't taken a trip to Finished() then we need todo it here. The
112 // issue we have is that this object may be deleted before Finished() is called
113 // which is quite dicey. So, we defer it until Finished() is called. This is
114 // only an issue server-side as we don't control the finish process.
115 //
116  if (reqP)
117  {reqP->rrMutex->Lock();
118  if (reqP->theRespond == this)
119  {reqP->theRespond = &ForceUnBind;
120  reqP->rrMutex->UnLock();
121  } else if (reqP->theRespond == 0) // Finish() has been called
122  {reqP->rrMutex->UnLock();
123  reqP->Dispose();
124  }
125  }
126 
127 // All done
128 //
129  spMutex.UnLock();
130 }
131 
132 /******************************************************************************/
133 /* A l e r t */
134 /******************************************************************************/
135 
137 {
138  XrdSsiMutexMon lck(spMutex);
139 
140 // If we have a request pointer then forward the alert. Otherwise, deep-six it
141 //
142  if (reqP) reqP->Alert(aMsg);
143  else aMsg.RecycleMsg(false);
144 }
145 
146 /******************************************************************************/
147 /* B i n d R e q u e s t */
148 /******************************************************************************/
149 
151 {
152  XrdSsiMutexMon lck(spMutex);
153 
154 // Get the request lock and link the request to this object and vice versa
155 //
156  rqstR.rrMutex->Lock();
157  reqP = &rqstR;
158  rqstR.theRespond = this;
159 
160 // Initialize the request object
161 //
162  rqstR.Resp.Init();
163  rqstR.errInfo.Clr();
164 
165 // Notify the request that the bind comleted (this is only used on the
166 // server to allow a pending finish request to be sent to the responder).
167 //
168  rqstR.BindDone();
169 
170 // Unlock the request. The responder is unlocked upon return
171 //
172  rqstR.rrMutex->UnLock();
173 }
174 
175 /******************************************************************************/
176 /* G e t R e q u e s t */
177 /******************************************************************************/
178 
180 {
181  XrdSsiMutexMon lck(spMutex);
182 
183 // If we have a request pointer, forward the call. Otherwise return nothing.
184 //
185  if (reqP) return reqP->GetRequest(dlen);
186  dlen = 0;
187  return 0;
188 }
189 
190 /******************************************************************************/
191 /* R e l e a s e R e q u e s t B u f f e r */
192 /******************************************************************************/
193 
195 {
196  XrdSsiMutexMon lck(spMutex);
197 
198 // If we have a request, forward the call (note we need to also get the
199 // the request lock to properly serialize this call).
200 //
201  if (reqP) reqP->ReleaseRequestBuffer();
202 }
203 
204 /******************************************************************************/
205 /* S e t M e t a d a t a */
206 /******************************************************************************/
207 
209 {
210  XrdSsiMutexMon lck(spMutex);
211 
212 // If we don't have a request or the args are invalid, return an error.
213 //
214  if (!reqP || blen < 0 || blen > MaxMetaDataSZ) return notPosted;
215 
216 // Post the metadata
217 //
218  reqP->rrMutex->Lock();
219  reqP->Resp.mdata = buff;
220  reqP->Resp.mdlen = blen;
221  reqP->rrMutex->UnLock();
222  return wasPosted;
223 }
224 
225 /******************************************************************************/
226 /* S e t E r r R e s p o n s e */
227 /******************************************************************************/
228 
230  int eNum)
231 {
232 
233 // Validate object for a response
234 //
236 
237 // Set the error response (we have the right locks now)
238 //
239  reqP->errInfo.Set(eMsg, eNum);
240  reqP->Resp.eMsg = reqP->errInfo.Get(reqP->Resp.eNum).c_str();
241  reqP->Resp.rType = XrdSsiRespInfo::isError;
242 
243 // Complete the response
244 //
246 }
247 
248 /******************************************************************************/
249 /* S e t R e s p o n s e */
250 /******************************************************************************/
251 
253 {
254 
255 // Validate object for a response
256 //
258 
259 // Set the response (we have the right locks now)
260 //
261  reqP->Resp.buff = buff;
262  reqP->Resp.blen = blen;
263  reqP->Resp.rType = XrdSsiRespInfo::isData;
264 
265 // Complete the response
266 //
268 }
269 
270 /******************************************************************************/
271 
273 {
274 
275 // Validate object for a response
276 //
278 
279 // Set the response (we have the right locks now)
280 //
281  reqP->Resp.fdnum = fdnum;
282  reqP->Resp.fsize = fsize;
283  reqP->Resp.rType = XrdSsiRespInfo::isFile;
284 
285 // Complete the response
286 //
288 }
289 
290 /******************************************************************************/
291 
293 {
294 
295 // Validate object for a response
296 //
298 
299 // Set the response (we have the right locks now)
300 //
301  reqP->Resp.eNum = 0;
302  reqP->Resp.strmP = strmP;
303  reqP->Resp.rType = XrdSsiRespInfo::isStream;
304 
305 // Complete the response
306 //
308 }
309 
310 /******************************************************************************/
311 /* U n B i n d R e q u e s t */
312 /******************************************************************************/
313 
315 {
316  XrdSsiMutexMon spMon(spMutex);
317 
318 // If we are not bound to a request, indicate an error.
319 //
320  if (!reqP) return false;
321 
322 // Lock the request and if Finished() was not called, indicate an error.
323 //
324  reqP->rrMutex->Lock();
325  if (reqP->theRespond != 0)
326  {reqP->rrMutex->UnLock();
327  return false;
328  }
329 
330 // We have a request pointer and Finish() was called; so do the actual unbind.
331 //
332  reqP->rrMutex->UnLock();
333  reqP->Dispose();
334  reqP = 0;
335  return true;
336 }
#define eMsg(x)
#define SSI_XEQ_RESPONSE
#define SSI_VAL_RESPONSE
void Clr()
Reset and clear error information.
void Set(const char *eMsg=0, int eNum=0, int eArg=0)
const std::string & Get(int &eNum) const
static void Dispose(XrdSsiRequest &reqR)
virtual void Alert(XrdSsiRespInfoMsg &aMsg)
Send or receive a server generated alert.
void ReleaseRequestBuffer()
virtual char * GetRequest(int &dlen)=0
virtual void RecycleMsg(bool sent=true)=0
char * GetRequest(int &dlen)
Status SetResponse(const char *buff, int blen)
void BindRequest(XrdSsiRequest &rqstR)
Status SetErrResponse(const char *eMsg, int eNum)
Status SetMetadata(const char *buff, int blen)
virtual ~XrdSsiResponder()
@ wasPosted
Success: The response was successfully posted.
virtual void Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel=false)=0
static const int MaxMetaDataSZ
2MB metadata limit
void Alert(XrdSsiRespInfoMsg &aMsg)
int mdlen
Metadata length.
const char * mdata
-> Metadata about response.