XRootD
XrdSsiTaskReal.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S s i T a s k R e a l . c c */
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 <cstdio>
31 #include <string>
32 
33 #include "XrdSsi/XrdSsiAtomics.hh"
34 #include "XrdSsi/XrdSsiRequest.hh"
35 #include "XrdSsi/XrdSsiRRAgent.hh"
36 #include "XrdSsi/XrdSsiRRInfo.hh"
37 #include "XrdSsi/XrdSsiScale.hh"
38 #include "XrdSsi/XrdSsiSessReal.hh"
39 #include "XrdSsi/XrdSsiTaskReal.hh"
40 #include "XrdSsi/XrdSsiTrace.hh"
41 #include "XrdSsi/XrdSsiUtils.hh"
42 
43 #include "XrdSys/XrdSysError.hh"
44 #include "XrdSys/XrdSysHeaders.hh"
45 #include "Xrd/XrdScheduler.hh"
46 
47 using namespace XrdSsi;
48 
49 /******************************************************************************/
50 /* L o c a l M a c r o s */
51 /******************************************************************************/
52 
53 #define DUMPIT(x,y) XrdSsiUtils::b2x(x,y,hexBuff,sizeof(hexBuff),dotBuff)<<dotBuff
54 
55 /******************************************************************************/
56 /* L o c a l S t a t i c s */
57 /******************************************************************************/
58 
59 namespace
60 {
61 const char *statName[] = {"isPend", "isWrite", "isSync",
62  "isReady", "isDone", "isDead"};
63 
64 XrdSsiSessReal voidSession(0, "voidSession", 0);
65 
66 std::string pName("ReadRecovery");
67 std::string pValue("false");
68 char zedData = 0;
69 }
70 
71 /******************************************************************************/
72 /* G l o b a l s */
73 /******************************************************************************/
74 
75 namespace XrdSsi
76 {
77 extern XrdSysError Log;
78 extern XrdScheduler *schedP;
79 extern XrdSsiScale sidScale;
80 }
81 
82 /******************************************************************************/
83 /* L o c a l C l a s s e s */
84 /******************************************************************************/
85 
86 namespace
87 {
88 class AlertMsg : public XrdSsiRespInfoMsg
89 {
90 public:
91 
92 void RecycleMsg(bool sent=true) {delete respObj; delete this;}
93 
94  AlertMsg(XrdCl::AnyObject *resp, char *dbuff, int dlen)
95  : XrdSsiRespInfoMsg(dbuff, dlen), respObj(resp) {}
96 
97  ~AlertMsg() {}
98 
99 private:
100 XrdCl::AnyObject *respObj;
101 };
102 
103 /******************************************************************************/
104 
105 class SchedEmsg : public XrdJob
106 {
107 public:
108 
109 void DoIt() {taskP->SendError();
110  delete this;
111  }
112 
113  SchedEmsg(XrdSsiTaskReal *tP) : taskP(tP) {}
114  ~SchedEmsg() {}
115 
116 private:
117 XrdSsiTaskReal *taskP;
118 };
119 }
120 
121 /******************************************************************************/
122 /* Private: A s k 4 R e s p */
123 /******************************************************************************/
124 
125 // Called with session mutex locked and returns with it unlocked!
126 
127 bool XrdSsiTaskReal::Ask4Resp()
128 {
129  EPNAME("Ask4Resp");
130 
131  XrdCl::XRootDStatus epStatus;
132  XrdSsiRRInfo rInfo;
133  XrdCl::Buffer qBuff(sizeof(unsigned long long));
134 
135 // Disable read recovery
136 //
137  sessP->epFile.SetProperty(pName, pValue);
138 
139 // Compose request to wait for the response
140 //
141  rInfo.Id(tskID); rInfo.Cmd(XrdSsiRRInfo::Rwt);
142  memcpy(qBuff.GetBuffer(), rInfo.Data(), sizeof(long long));
143 
144 // Do some debugging
145 //
146  DEBUG("Calling fcntl for response.");
147 
148 // Issue the command to field the response
149 //
150  epStatus = sessP->epFile.Fcntl(qBuff, (ResponseHandler *)this, tmOut);
151 
152 // Dianose any errors. If any occurred we simply return an error response but
153 // otherwise let this go as it really is not a logic error.
154 //
155  if (!epStatus.IsOK()) return RespErr(&epStatus);
156  mhPend = true;
157  tStat = isSync;
158  sessP->UnLock();
159  return true;
160 }
161 
162 /******************************************************************************/
163 /* D e t a c h */
164 /******************************************************************************/
165 
166 void XrdSsiTaskReal::Detach(bool force)
167 { tStat = isDead;
168  if (force) sessP = &voidSession;
169 }
170 
171 /******************************************************************************/
172 /* F i n i s h e d */
173 /******************************************************************************/
174 
175 // Note that if we are called then Finished() must have been called while we
176 // were still in the open phase.
177 
179  const XrdSsiRespInfo &rInfo, bool cancel)
180 {
181  EPNAME("TaskFinished");
182  XrdSsiMutexMon rHelp(sessP->MutexP());
183 
184 // Do some debugging
185 //
186  DEBUG("Request="<<&rqstR<<" cancel="<<cancel);
187 
188 // We should do an unbind here but that is overkill. All we need to do is
189 // clear the pointer to the request object.
190 //
192 
193 // If we can kill this task right now, clean up. Otherwise, the message
194 // handler will clean things up.
195 //
196  if (Kill()) sessP->TaskFinished(this);
197  else {DEBUG("Task removal deferred.");}
198 }
199 
200 /******************************************************************************/
201 /* Private: G e t R e s p */
202 /******************************************************************************/
203 
204 XrdSsiTaskReal::respType XrdSsiTaskReal::GetResp(XrdCl::AnyObject **respP,
205  char *&dbuff, int &dbL)
206 {
207  EPNAME("GetResp");
208  XrdCl::AnyObject *response = *respP;
209  XrdCl::Buffer *buffP;
210  XrdSsiRRInfoAttn *mdP;
211  char *cdP;
212  unsigned int mdL, pxL, n;
213  respType xResp;
214 
215 // Make sure that the [meta]data is actually present
216 //
217  response->Get(buffP);
218  if (!buffP || !(cdP = buffP->GetBuffer()))
219  {DEBUG("Responding with stream.");
220  return isStream;
221  }
222 
223 // Validate the header
224 //
225  if ((n=buffP->GetSize()) < sizeof(XrdSsiRRInfoAttn)) return isBad;
226  mdP = (XrdSsiRRInfoAttn *)cdP;
227  mdL = ntohl(mdP->mdLen);
228  pxL = ntohs(mdP->pfxLen);
229  dbL = n - mdL - pxL;
230  if (pxL < sizeof(XrdSsiRRInfoAttn) || dbL < 0) return isBad;
231 
232 // This may be an alert message, check for that now
233 //
234  if (mdP->tag == XrdSsiRRInfoAttn::alrtResp)
235  {char hexBuff[16],dotBuff[4];
236  dbuff = cdP+pxL; dbL = mdL;
237  DEBUG("Posting "<<dbL<<" byte alert (0x"<<DUMPIT(dbuff,dbL)<<")");
238  return isAlert;
239  }
240 
241 // Extract out the metadata
242 //
243  if (mdL)
244  {char hexBuff[16],dotBuff[4];
245  DEBUG(mdL <<" byte metadata set (0x" <<DUMPIT(cdP+pxL,mdL)<<")");
246  SetMetadata(cdP+pxL, mdL);
247  }
248 
249 // Extract out the data
250 //
251  if (mdP->tag == XrdSsiRRInfoAttn::fullResp)
252  {dbuff = (dbL ? cdP+mdL+pxL : &zedData);
253  xResp = isData;
254  DEBUG("Responding with " <<dbL <<" data bytes.");
255  }
256  else {xResp = isStream;
257  DEBUG("Responding with stream.");
258  }
259 
260 // Save the response buffer if we will be referecing it later
261 //
262  if (mdL || dbL)
263  {mdResp = response;
264  *respP = 0;
265  }
266 
267 // All done
268 //
269  return xResp;
270 }
271 
272 /******************************************************************************/
273 /* K i l l */
274 /******************************************************************************/
275 
276 bool XrdSsiTaskReal::Kill() // Called with session mutex locked!
277 {
278  EPNAME("TaskKill");
279  XrdSsiRRInfo rInfo;
280 
281 // Do some debugging
282 //
283  DEBUG("Status="<<statName[tStat]<<" defer=" <<defer<<" mhPend="<<mhPend);
284 
285 // Affect proper procedure
286 //
287  switch(tStat)
288  {case isWrite: break;
289  case isSync: break;
290  case isReady: break;
291  case isDone: tStat = isDead;
292  return !(mhPend || defer);
293  break;
294  case isDead: return !(mhPend || defer);
295  break;
296  case isPend: tStat = isDead;
297  return !(mhPend || defer);
298  break;
299  default: char mBuff[32];
300  snprintf(mBuff, sizeof(mBuff), "%d", tStat);
301  Log.Emsg("TaskKill", "Invalid state", mBuff);
302  tStat = isDead;
303  return false;
304  break;
305  }
306 
307 // The tricky thing here is that a kill came when we are actully in the process
308 // of writing the request. If so, we need to hold until that finished to keep
309 // valgring happy (i.e. nt writing from unallocated memory). So, we will have to
310 // wait until he write catually occurs before continuing (yech -- thread hung).
311 //
312  if (tStat == isWrite && mhPend)
313  {XrdSysSemaphore wSem(0);
314  wPost = &wSem;
315  DEBUG("Waiting for write event.");
316  sessP->UnLock();
317  wSem.Wait();
318  sessP->Lock();
319  }
320 
321 // If we are here then the request is potentially still active at the server.
322 // We will send a synchronous cancel request. It shouldn't take long. Note
323 // that, for now, we ignore any errors as we don't have a recovery plan.
324 //
325  rInfo.Id(tskID); rInfo.Cmd(XrdSsiRRInfo::Can);
326  DEBUG("Sending cancel request.");
327  XrdCl::XRootDStatus Status = sessP->epFile.Truncate(rInfo.Info(), tmOut);
328 
329 
330 // If we are in the message handler or if we have a message pending, then
331 // the message handler will dispose of the task.
332 //
333  tStat = isDead;
334  DEBUG("Returning " <<!(mhPend || defer));
335  return !(mhPend || defer);
336 }
337 
338 /******************************************************************************/
339 /* Private: R e s p E r r */
340 /******************************************************************************/
341 
342 // Called with session mutex locked and returns with it unlocked!
343 
344 bool XrdSsiTaskReal::RespErr(XrdCl::XRootDStatus *status)
345 {
346  EPNAME("RespErr");
347  std::string eTxt;
348  int eNum = XrdSsiUtils::GetErr(*status, eTxt);
349 
350 // Indicate we are done and unlock the session. The caller should have deferred
351 // the processing of Finished() if this object will continue to be referenced.
352 //
353  tStat = isDone;
354  if (sessP)
355  {sessP->UnHold(false);
356  sessP->UnLock();
357  }
358 
359 // Reflect an error to the request object.
360 //
361  DEBUG("Posting error " <<eNum <<": " <<eTxt.c_str());
362  SetErrResponse(eTxt.c_str(), eNum);
363  return false;
364 }
365 
366 /******************************************************************************/
367 /* S c h e d E r r o r */
368 /******************************************************************************/
369 
370 // Called with sessMutex locked!
371 
373 {
374 // Copy the error information if so supplied.
375 //
376  if (eInfo) errInfo = *eInfo;
377 
378 // Schedule the error to avoid lock clashes. Make sure Finished calls deferred.
379 // The target (SendError) will decrease the defer refcount (ugly but true).
380 //
381  defer++;
382  XrdSsi::schedP->Schedule((XrdJob *)(new SchedEmsg(this)));
383 }
384 
385 /******************************************************************************/
386 /* S e n d E r r o r */
387 /******************************************************************************/
388 
389 void XrdSsiTaskReal::SendError() // Called with defer > 0!
390 {
391  EPNAME("SendError");
392 
393 // Lock the associated session
394 //
395  sessP->Lock();
396  DEBUG("Status="<<statName[tStat]<<" defer=" <<defer<<" mhPend="<<mhPend);
397 
398 // If there was no call to finished then we need to send an error response
399 // which may precipitate a finished call now or later. Defer should be set
400 // with anticipation that we will decrease it after the callback.
401 //
402  if (tStat != isDead)
403  {int eNum;
404  const char *eTxt = errInfo.Get(eNum).c_str();
405  sessP->UnLock();
406  SetErrResponse(eTxt, eNum);
407  sessP->Lock();
408  defer--;
409  if (tStat != isDead)
410  {sessP->UnLock();
411  return;
412  }
413  }
414 
415 // If it is safe to do so, finish up everything here
416 //
417 
418  if (mhPend || defer)
419  {DEBUG("Defering TaskFinished."<<" defer=" <<defer<<" mhPend="<<mhPend);
420  sessP->UnLock();
421  } else {
422  DEBUG("Calling TaskFinished");
423  sessP->UnLock();
424  sessP->TaskFinished(this);
425  }
426 }
427 
428 /******************************************************************************/
429 /* S e n d R e q u e s t */
430 /******************************************************************************/
431 
432 // Called with sessMutex locked!
433 
434 bool XrdSsiTaskReal::SendRequest(const char *node)
435 {
437  XrdSsiRRInfo rrInfo;
438  char *reqBuff;
439  int reqBlen;
440 
441 // We must be in pend state to send a request. If we are not then the request
442 // must have been cancelled. It also means we have a logic error if the
443 // state is not isDead as we can't finish off the task and leak memory.
444 //
445  if (tStat != isPend)
446  {if (tStat == isDead) sessP->TaskFinished(this);
447  else Log.Emsg("SendRequest", "Invalid state", statName[tStat],
448  "; should be isPend!");
449  return false;
450  }
451 
452 // Establish the endpoint
453 //
455 
456 // Get the request information. Make sure to defer Finish() calls.
457 //
458  defer++;
459  reqBuff = XrdSsiRRAgent::Request(this)->GetRequest(reqBlen);
460  defer--;
461 
462 // It's possible that GetRequest() called finished so process that here.
463 //
464  if (tStat == isDead)
465  {sessP->TaskFinished(this);
466  return false;
467  }
468 
469 
470 // Construct the info for this request
471 //
472  rrInfo.Id(tskID);
473  rrInfo.Size(reqBlen);
474  tStat = isWrite;
475 
476 // If we are writing a zero length message, we must fake a request as zero
477 // zero length messages are normally deep-sixed.
478 //
479  if (!reqBlen)
480  {reqBuff = &zedData;
481  reqBlen = 1;
482  }
483 
484 // Issue the write
485 //
486  Status = sessP->epFile.Write(rrInfo.Info(), (uint32_t)reqBlen, reqBuff,
487  (XrdCl::ResponseHandler *)this, tmOut);
488 
489 // Determine ending status. If it's bad, schedule an error. Note that calls to
490 // Finished() will be deferred until the error thread gets control.
491 //
492  if (!Status.IsOK())
493  {XrdSsiUtils::SetErr(Status, errInfo);
494  SchedError();
495  return false;
496  }
497 
498 // Indicate a message handler call outstanding
499 //
500  mhPend = true;
501  return true;
502 }
503 
504 /******************************************************************************/
505 /* S e t B u f f */
506 /******************************************************************************/
507 
509  char *buff, int blen, bool &last)
510 {
511  EPNAME("TaskSetBuff");
512  XrdSsiMutexMon rHelp(sessP->MutexP());
513  XrdCl::XRootDStatus epStatus;
514  XrdSsiRRInfo rrInfo;
515  union {uint32_t ubRead; int ibRead;};
516 
517 // Check if this is a proper call or we have reached EOF
518 //
519  DEBUG("ReadSync status=" <<statName[tStat]);
520  if (tStat != isReady)
521  {if (tStat == isDone) return 0;
522  eRef.Set("Stream is not active", ENODEV);
523  return -1;
524  }
525 
526 // Prepare to issue the read
527 //
528  rrInfo.Id(tskID);
529 
530 // Issue a read
531 //
532  epStatus = sessP->epFile.Read(rrInfo.Info(),(uint32_t)blen,buff,ubRead,tmOut);
533  if (epStatus.IsOK())
534  {if (ibRead < blen) {tStat = isDone; last = true;}
535  DEBUG("ReadSync returning " <<ibRead <<" bytes.");
536  return ibRead;
537  }
538 
539 // We failed, return an error
540 //
541  XrdSsiUtils::SetErr(epStatus, eRef);
542  tStat = isDone;
543  DEBUG("ReadSync error; " <<epStatus.ToStr());
544  return -1;
545 }
546 
547 /******************************************************************************/
548 
549 bool XrdSsiTaskReal::SetBuff(XrdSsiErrInfo &eRef, char *buff, int blen)
550 {
551  EPNAME("TaskSetBuff");
552  XrdSsiMutexMon rHelp(sessP->MutexP());
553  XrdCl::XRootDStatus epStatus;
554  XrdSsiRRInfo rrInfo;
555 
556 // Check if this is a proper call or we have reached EOF
557 //
558  DEBUG("ReadAsync Status=" <<statName[tStat]);
559  if (tStat != isReady)
560  {eRef.Set("Stream is not active", ENODEV);
561  return false;
562  }
563 
564 // We only support (for now) one read at a time
565 //
566  if (mhPend)
567  {eRef.Set("Stream is already active", EINPROGRESS);
568  return false;
569  }
570 
571 // Make sure the buffer length is valid
572 //
573  if (blen <= 0)
574  {eRef.Set("Buffer length invalid", EINVAL);
575  return false;
576  }
577 
578 // Prepare to issue the read
579 //
580  rrInfo.Id(tskID);
581 
582 // Issue a read
583 //
584  dataBuff = buff; dataRlen = blen;
585  epStatus = sessP->epFile.Read(rrInfo.Info(), (uint32_t)blen, buff,
586  (XrdCl::ResponseHandler *)this, tmOut);
587 
588 // If success then indicate we are pending and return
589 //
590  if (epStatus.IsOK()) {mhPend = true; return true;}
591 
592 // We failed, return an error
593 //
594  XrdSsiUtils::SetErr(epStatus, eRef);
595  tStat = isDone;
596  DEBUG("ReadAsync error; " <<epStatus.ToStr());
597  return false;
598 }
599 
600 /******************************************************************************/
601 /* X e q E v e n t */
602 /******************************************************************************/
603 
605  XrdCl::AnyObject **respP)
606 {
607  EPNAME("TaskXeqEvent");
608 
609  XrdCl::AnyObject *response = *respP;
610  XrdSsiRespInfoMsg *aMsg;
611  char *dBuff;
612  union {uint32_t ubRead; int ibRead;};
613  int dLen;
614  TaskStat Tstat;
615  bool last, aOK = status->IsOK();
616 
617 // Obtain a lock and indicate the any Finish() calls should be deferred until
618 // we return from this method. The reason is that any callback that we do here
619 // may precipitate a Finish() call not to mention some other thread doing so.
620 //
621  XrdSsiMutexMon monMtx(sessP->MutexP());
622  defer++;
623  mhPend = false;
624 
625 // Do some debugging
626 //
627  DEBUG("aOK="<<aOK<<" status="<<statName[tStat]<<" defer=" <<defer);
628 
629 // Affect proper response
630 //
631  switch(tStat)
632  {case isWrite:
633  if (!aOK)
634  {RespErr(status); // Unlocks the mutex!
635  monMtx.Reset();
636  return 1;
637  }
638  DEBUG("Write completed.");
639  if (wPost)
640  {DEBUG("Posting killer.");
641  wPost->Post(); wPost = 0;
642  return 1;
643  }
644  DEBUG("Calling RelBuff.");
645  ReleaseRequestBuffer();
646  if (tStat == isWrite)
647  {monMtx.Reset();
648  return (Ask4Resp() ? 0 : 1); // Unlocks the mutex!
649  }
650  return 1;
651 
652  case isSync:
653  monMtx.Reset();
654  if (!aOK) return (RespErr(status) ? 0 : 1); // Unlocks the mutex!
655 
656  if (response) switch(GetResp(respP, dBuff, dLen))
657  {case isAlert: aMsg = new AlertMsg(*respP, dBuff, dLen);
658  *respP = 0;
659  sessP->UnLock();
660  XrdSsiRRAgent::Alert(*rqstP, *aMsg);
661  sessP->Lock();
662  if (tStat == isSync)
663  return (Ask4Resp() ? 0 : 1);
664  Tstat = tStat;
665  sessP->UnLock();
666  return (Tstat != isDead ? 0 : 1);
667  break;
668  case isData: tStat = isDone; sessP->UnLock();
669  SetResponse(dBuff, dLen);
670  break;
671  case isStream: tStat = isReady; sessP->UnLock();
672  SetResponse((XrdSsiStream *)this);
673  break;
674  default: tStat = isDone; sessP->UnLock();
675  SetErrResponse("Invalid response", EFAULT);
676  break;
677  } else {
678  tStat = isDone; sessP->UnLock();
679  SetErrResponse("Missing response", EFAULT);
680  }
681  return 0;
682 
683  case isReady:
684  break;
685 
686  case isDead:
687  return 1;
688 
689  default: char mBuff[32];
690  snprintf(mBuff, sizeof(mBuff), "%d", tStat);
691  Log.Emsg("TaskXeqEvent", "Invalid state", mBuff);
692  return 1;
693  }
694 
695 // Handle incoming response data. The session mutex is still locked!
696 //
697  if (!aOK || !response)
698  {ibRead = -1;
699  if (!aOK) XrdSsiUtils::SetErr(*status, XrdSsiRRAgent::ErrInfoRef(rqstP));
700  else XrdSsiRRAgent::ErrInfoRef(rqstP).Set("Missing response", EFAULT);
701  } else {
702  XrdCl::ChunkInfo *cInfo = 0;
703  response->Get(cInfo);
704  ubRead = (cInfo ? cInfo->length : 0);
705  }
706 
707 // Reflect the response to the request as this was an async receive. We may not
708 // reference this object after the UnLock() as Finished() might be called.
709 //
710  if (ibRead < dataRlen) {tStat = isDone; dataRlen = ibRead;}
711  dBuff = dataBuff;
712  last = tStat == isDone;
713  sessP->UnLock();
714  DEBUG("Calling ProcessResponseData; len="<<ibRead<<" last="<<last);
715  rqstP->ProcessResponseData(XrdSsiRRAgent::ErrInfoRef(rqstP),
716  dBuff, ibRead, last);
717 
718 // All done
719 //
720  return 0;
721 }
722 
723 /******************************************************************************/
724 /* X e q E v F i n */
725 /******************************************************************************/
726 
728 {
729  EPNAME("TaskXeqEvFin");
730 
731 // Obtain a lock and remove defer flag (protected by the lock)
732 //
733  sessP->Lock();
734  defer--;
735  DEBUG("Status="<<statName[tStat]<<" defer=" <<defer<<" mhPend="<<mhPend);
736 
737 
738 // Check if finished has been called while we were deferred or if this is an
739 // orphaned task due to a session stop request.
740 //
741  if (tStat == isDead)
742  {if (sessP != &voidSession)
743  {if (mhPend || defer) {DEBUG("Defering TaskFinished.");}
744  else {DEBUG("Calling TaskFinished");
745  sessP->UnLock();
746  sessP->TaskFinished(this);
747  }
748  } else {
749  DEBUG("Deleting orphaned task.");
750  sessP->UnLock();
751  delete this;
752  }
753  } else sessP->UnLock();
754 }
int DoIt(int argpnt, int argc, char **argv, bool singleshot)
Definition: XrdAccTest.cc:262
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define DUMPIT(x, y)
void Get(Type &object)
Retrieve the object being held.
Binary blob representation.
Definition: XrdClBuffer.hh:34
const char * GetBuffer(uint32_t offset=0) const
Get the message buffer.
Definition: XrdClBuffer.hh:72
uint32_t GetSize() const
Get the size of the message.
Definition: XrdClBuffer.hh:132
Handle an async response.
std::string ToStr() const
Convert to string.
Definition: XrdJob.hh:43
void Schedule(XrdJob *jp)
void Set(const char *eMsg=0, int eNum=0, int eArg=0)
static XrdSsiRequest * Request(XrdSsiResponder *rP)
static XrdSsiErrInfo & ErrInfoRef(XrdSsiRequest *rP)
static void Alert(XrdSsiRequest &reqR, XrdSsiRespInfoMsg &aMsg)
static void ResetResponder(XrdSsiResponder *rP)
static void SetNode(XrdSsiRequest *rP, const char *name)
void Size(unsigned int sz)
Definition: XrdSsiRRInfo.hh:60
const unsigned char * Data()
Definition: XrdSsiRRInfo.hh:50
unsigned long long Info()
Definition: XrdSsiRRInfo.hh:64
void Cmd(Opc cmd)
Definition: XrdSsiRRInfo.hh:45
void Id(unsigned int id)
Definition: XrdSsiRRInfo.hh:52
virtual char * GetRequest(int &dlen)=0
void Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel=false)
int SetBuff(XrdSsiErrInfo &eRef, char *buff, int blen, bool &last)
int XeqEvent(XrdCl::XRootDStatus *status, XrdCl::AnyObject **respP)
void SchedError(XrdSsiErrInfo *eInfo=0)
bool SendRequest(const char *node)
void Detach(bool force=false)
static int GetErr(XrdCl::XRootDStatus &Status, std::string &eText)
Definition: XrdSsiUtils.cc:191
static void SetErr(XrdCl::XRootDStatus &Status, XrdSsiErrInfo &eInfo)
Definition: XrdSsiUtils.cc:232
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdScheduler * schedP
Definition: XrdSsiClient.cc:74
XrdSsiScale sidScale
XrdSysError Log
Describe a data chunk for vector read.
uint32_t length
offset in the file
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124
static const int fullResp
Definition: XrdSsiRRInfo.hh:92
unsigned short pfxLen
Definition: XrdSsiRRInfo.hh:97
unsigned int mdLen
Definition: XrdSsiRRInfo.hh:98
static const int alrtResp
Definition: XrdSsiRRInfo.hh:91