XRootD
XrdSsiFileSess.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S s i F i l e S e s s . c c */
4 /* */
5 /* (c) 2016 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 <fcntl.h>
31 #include <stddef.h>
32 #include <cstdio>
33 #include <cstring>
34 #include <arpa/inet.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/uio.h>
38 
39 #include "XrdNet/XrdNetAddrInfo.hh"
40 
41 #include "XrdOuc/XrdOucBuffer.hh"
42 #include "XrdOuc/XrdOucEnv.hh"
43 #include "XrdOuc/XrdOucERoute.hh"
44 #include "XrdOuc/XrdOucPList.hh"
45 
46 #include "XrdSec/XrdSecEntity.hh"
47 
48 #include "XrdSfs/XrdSfsAio.hh"
49 
50 #include "XrdSsi/XrdSsiEntity.hh"
51 #include "XrdSsi/XrdSsiFileSess.hh"
52 #include "XrdSsi/XrdSsiProvider.hh"
53 #include "XrdSsi/XrdSsiRRInfo.hh"
54 #include "XrdSsi/XrdSsiService.hh"
55 #include "XrdSsi/XrdSsiSfs.hh"
56 #include "XrdSsi/XrdSsiStats.hh"
57 #include "XrdSsi/XrdSsiStream.hh"
58 #include "XrdSsi/XrdSsiTrace.hh"
59 #include "XrdSsi/XrdSsiUtils.hh"
60 
61 #include "XrdSys/XrdSysE2T.hh"
62 #include "XrdSys/XrdSysError.hh"
63 
64 /******************************************************************************/
65 /* G l o b a l s */
66 /******************************************************************************/
67 
68 namespace XrdSsi
69 {
70 extern XrdOucBuffPool *BuffPool;
71 extern XrdSsiProvider *Provider;
73 extern XrdSsiStats Stats;
74 extern XrdSysError Log;
75 extern int respWT;
76 extern int minRSZ;
77 extern int maxRSZ;
78 }
79 
80 using namespace XrdSsi;
81 
82 /******************************************************************************/
83 /* L o c a l M a c r o s */
84 /******************************************************************************/
85 
86 #define DUMPIT(x,y) XrdSsiUtils::b2x(x,y,hexBuff,sizeof(hexBuff),dotBuff)<<dotBuff
87 
88 /******************************************************************************/
89 /* L o c a l C l a s s e s */
90 /******************************************************************************/
91 
92 namespace
93 {
94 class nullCallBack : public XrdOucEICB
95 {
96 public:
97 
98 void Done(int &Result, XrdOucErrInfo *eInfo, const char *Path=0) {}
99 
100 int Same(unsigned long long arg1, unsigned long long arg2) {return 0;}
101 
102  nullCallBack() {}
103 virtual ~nullCallBack() {}
104 };
105 
106 nullCallBack nullCB;
107 };
108 
109 /******************************************************************************/
110 /* S t a t i c M e m b e r s */
111 /******************************************************************************/
112 
113 XrdSysMutex XrdSsiFileSess::arMutex;
114 XrdSsiFileSess *XrdSsiFileSess::freeList = 0;
115 int XrdSsiFileSess::freeNum = 0;
116 int XrdSsiFileSess::freeNew = 0;
117 int XrdSsiFileSess::freeMax = 100;
118 int XrdSsiFileSess::freeAbs = 200;
119 
120 bool XrdSsiFileSess::authDNS = false;
121 
122 /******************************************************************************/
123 /* A l l o c */
124 /******************************************************************************/
125 
127 {
128  XrdSsiFileSess *fsP;
129 
130 // Get a lock
131 //
132  arMutex.Lock();
133 
134 // Get either a reuseable object or a new one
135 //
136  if ((fsP = freeList))
137  {freeNum--;
138  freeList = fsP->nextFree;
139  arMutex.UnLock();
140  fsP->Init(einfo, user, true);
141  } else {
142  freeNew++;
143  if (freeMax <= freeAbs && freeNew >= freeMax/2)
144  {freeMax += freeMax/2;
145  freeNew = 0;
146  }
147  arMutex.UnLock();
148  fsP = new XrdSsiFileSess(einfo, user);
149  }
150 
151 // Return the object
152 //
153  return fsP;
154 }
155 
156 /******************************************************************************/
157 /* A t t n I n f o */
158 /******************************************************************************/
159 
161  unsigned int reqID)
162 // Called with the request mutex locked!
163 {
164  EPNAME("AttnInfo");
165  struct AttnResp {struct iovec ioV[4]; XrdSsiRRInfoAttn aHdr;};
166 
167  AttnResp *attnResp;
168  char *mBuff;
169  int n, ioN = 2;
170  bool doFin;
171 
172 // If there is no data we can send back to the client in the attn response,
173 // then simply reply with a short message to make the client come back.
174 //
175  if (!respP->mdlen)
176  {if (respP->rType != XrdSsiRespInfo::isData
177  || respP->blen > XrdSsiResponder::MaxDirectXfr)
178  {eInfo.setErrInfo(0, "");
179  return false;
180  }
181  }
182 
183 // We will be constructing the response in the message buffer. This is
184 // gauranteed to be big enough for our purposes so no need to check the size.
185 //
186  mBuff = eInfo.getMsgBuff(n);
187 
188 // Initialize the response
189 //
190  attnResp = (AttnResp *)mBuff;
191  memset(attnResp, 0, sizeof(AttnResp));
192  attnResp->aHdr.pfxLen = htons(sizeof(XrdSsiRRInfoAttn));
193 
194 // Fill out iovec to point to our header
195 //
196 //?attnResp->ioV[0].iov_len = sizeof(XrdSsiRRInfoAttn) + respP->mdlen;
197  attnResp->ioV[1].iov_base = mBuff+offsetof(struct AttnResp, aHdr);
198  attnResp->ioV[1].iov_len = sizeof(XrdSsiRRInfoAttn);
199 
200 // Fill out the iovec for the metadata if we have some
201 //
202  if (respP->mdlen)
203  {attnResp->ioV[2].iov_base = (void *)respP->mdata;
204  attnResp->ioV[2].iov_len = respP->mdlen; ioN = 3;
205  attnResp->aHdr.mdLen = htonl(respP->mdlen);
206  Stats.Bump(Stats.RspMDBytes, respP->mdlen);
207  if (QTRACE(Debug))
208  {char hexBuff[16],dotBuff[4];
209  DEBUG(reqID <<':' <<gigID <<' ' <<respP->mdlen <<" byte metadata (0x"
210  <<DUMPIT(respP->mdata,respP->mdlen) <<") sent.");
211  }
212  }
213 
214 // Check if we have actual data here as well and can send it along
215 //
216  if (respP->rType == XrdSsiRespInfo::isData
217  && respP->blen+respP->mdlen <= XrdSsiResponder::MaxDirectXfr)
218  {if (respP->blen)
219  {attnResp->ioV[ioN].iov_base = (void *)respP->buff;
220  attnResp->ioV[ioN].iov_len = respP->blen; ioN++;
221  }
222  attnResp->aHdr.tag = XrdSsiRRInfoAttn::fullResp; doFin = true;
223  }
224  else {attnResp->aHdr.tag = XrdSsiRRInfoAttn::pendResp; doFin = false;}
225 
226 // If we sent the full response we must remove the request from the request
227 // table as it will get finished off when the response is actually sent.
228 //
229  if (doFin)
231  if (!(rqstP = rTab.LookUp(reqID)))
232  {eInfo.setErrInfo(0, "");
233  return false;
234  }
235  attnFinCallBack.setReq(std::move(rqstP));
236  eInfo.setErrCB(&attnFinCallBack);
237  rTab.Del(reqID);
238  }
239 
240 // Setup to have metadata actually sent to the requestor
241 //
242  eInfo.setErrCode(ioN);
243  return doFin;
244 }
245 
246 /******************************************************************************/
247 /* c l o s e */
248 /******************************************************************************/
249 
250 int XrdSsiFileSess::close(bool viaDel)
251 /*
252  Function: Close the file object.
253 
254  Input: None
255 
256  Output: Always returns SFS_OK
257 */
258 {
259  const char *epname = "close";
260 
261 // Do some debugging
262 //
263  DEBUG((gigID ? gigID : "???") <<" del=" <<viaDel);
264 
265 // Collect statistics if this is a delete which implies a lost connection
266 //
267  if (viaDel)
268  {int rCnt = rTab.Num();
269  if (rCnt) Stats.Bump(Stats.ReqFinForce, rCnt);
270  }
271 
272 // Run through all outstanding requests and comlete them
273 //
274  rTab.Reset();
275 
276 // Free any in-progress buffers
277 //
278  if (inProg)
279  {if (oucBuff) {oucBuff->Recycle(); oucBuff = 0;}
280  inProg = false;
281  }
282 
283 // Clean up storage
284 //
285  isOpen = false;
286  return SFS_OK;
287 }
288 
289 /******************************************************************************/
290 /* f c t l */
291 /******************************************************************************/
292 
293 int XrdSsiFileSess::fctl(const int cmd,
294  int alen,
295  const char *args,
296  const XrdSecEntity *client)
297 {
298  static const char *epname = "fctl";
299  XrdSsiRRInfo *rInfo;
301  unsigned int reqID;
302 
303 // If this isn't the special query, then return an error
304 //
305  if (cmd != SFS_FCTL_SPEC1)
306  return XrdSsiUtils::Emsg(epname, ENOTSUP, "fctl", gigID, *eInfo);
307 
308 // Caller wishes to find out if a request is ready and wait if it is not
309 //
310  if (!args || alen < (int)sizeof(XrdSsiRRInfo))
311  return XrdSsiUtils::Emsg(epname, EINVAL, "fctl", gigID, *eInfo);
312 
313 // Grab the request identifier
314 //
315  rInfo = (XrdSsiRRInfo *)args;
316  reqID = rInfo->Id();
317 
318 // Do some debugging
319 //
320  DEBUG(reqID <<':' <<gigID <<" query resp status");
321 
322 // Find the request
323 //
324  if (!(rqstP = rTab.LookUp(reqID)))
325  return XrdSsiUtils::Emsg(epname, ESRCH, "fctl", gigID, *eInfo);
326 
327 // Check if a response is waiting for the caller
328 //
329  if (rqstP->WantResponse(*eInfo))
330  {DEBUG(reqID <<':' <<gigID <<" resp ready");
332  return SFS_DATAVEC;
333  }
334 
335 // Put this client into callback state
336 //
337  DEBUG(reqID <<':' <<gigID <<" resp not ready");
338  fctlCallBack.setReq(std::move(rqstP));
339 
340  eInfo->setErrCB(&fctlCallBack);
341  eInfo->setErrInfo(respWT, "");
343  return SFS_STARTED;
344 }
345 
346 /******************************************************************************/
347 /* Private: I n i t */
348 /******************************************************************************/
349 
350 void XrdSsiFileSess::Init(XrdOucErrInfo &einfo, const char *user, bool forReuse)
351 {
352  tident = (user ? strdup(user) : strdup(""));
353  eInfo = &einfo;
354  gigID = 0;
355  fsUser = 0;
356  xioP = 0;
357  oucBuff = 0;
358  reqSize = 0;
359  reqLeft = 0;
360  isOpen = false;
361  inProg = false;
362  if (forReuse)
363  {eofVec.Reset();
364  rTab.Clear();
365  }
366 }
367 
368 /******************************************************************************/
369 /* Private: N e w R e q u e s t */
370 /******************************************************************************/
371 
372 bool XrdSsiFileSess::NewRequest(unsigned int reqid,
373  XrdOucBuffer *oP,
374  XrdSfsXioHandle bR,
375  int rSz)
376 {
377  XrdSsiFileReq *reqP;
378 
379 // Allocate a new request object
380 //
381  if (!(reqP=XrdSsiFileReq::Alloc(eInfo,&fileResource,this,gigID,tident,reqid)))
382  return false;
383 
384 // Add it to the table
385 //
386  XrdSsiRRTableItem<XrdSsiFileReq> rqstP = rTab.Add(reqP, reqid);
387  if (!rqstP)
388  {delete reqP;
389  return false;
390  }
391 
392 // Activate the request
393 //
394  inProg = false;
395  rqstP->Activate(oP, bR, rSz);
396  return true;
397 }
398 
399 /******************************************************************************/
400 /* o p e n */
401 /******************************************************************************/
402 
403 int XrdSsiFileSess::open(const char *path, // In
404  XrdOucEnv &theEnv, // In
405  XrdSfsFileOpenMode open_mode) // In
406 /*
407  Function: Open the file `path' in the mode indicated by `open_mode'.
408 
409  Input: path - The fully qualified name of the resource.
410  theEnv - Environmental information.
411  open_mode - It must contain only SFS_O_RDWR.
412 
413  Output: Returns SFS_OK upon success, otherwise SFS_ERROR is returned.
414 */
415 {
416  static const char *epname = "open";
417  XrdSsiErrInfo errInfo;
418  const char *eText;
419  int eNum;
420 
421 // Verify that this object is not already associated with an open file
422 //
423  if (isOpen)
424  return XrdSsiUtils::Emsg(epname, EADDRINUSE, "open session", path, *eInfo);
425 
426 // Make sure the open flag is correct (we now open this R/O so don't check)
427 //
428 // if (open_mode != SFS_O_RDWR)
429 // return XrdSsiUtils::Emsg(epname, EPROTOTYPE, "open session", path, *eInfo);
430 
431 // Setup the file resource object
432 //
433  fileResource.Init(path, theEnv, authDNS);
434 
435 // Notify the provider that we will be executing a request
436 //
437  if (Service->Prepare(errInfo, fileResource))
438  {const char *usr = fileResource.rUser.c_str();
439  if (!(*usr)) gigID = strdup(path);
440  else {char gBuff[2048];
441  snprintf(gBuff, sizeof(gBuff), "%s:%s", usr, path);
442  gigID = strdup(gBuff);
443  }
444  DEBUG(gigID <<" prepared.");
445  isOpen = true;
446  return SFS_OK;
447  }
448 
449 // Get error information
450 //
451  eText = errInfo.Get(eNum).c_str();
452  if (!eNum)
453  {eNum = ENOMSG; eText = "Provider returned invalid prepare response.";}
454 
455 // Decode the error
456 //
457  switch(eNum)
458  {case EAGAIN:
459  if (!eText || !(*eText)) break;
460  eNum = errInfo.GetArg();
461  DEBUG(path <<" --> " <<eText <<':' <<eNum);
462  eInfo->setErrInfo(eNum, eText);
464  return SFS_REDIRECT;
465  break;
466  case EBUSY:
467  eNum = errInfo.GetArg();
468  if (!eText || !(*eText)) eText = "Provider is busy.";
469  DEBUG(path <<" dly " <<eNum <<' ' <<eText);
470  if (eNum <= 0) eNum = 1;
471  eInfo->setErrInfo(eNum, eText);
473  return eNum;
474  break;
475  default:
476  if (!eText || !(*eText)) eText = XrdSysE2T(eNum);
477  DEBUG(path <<" err " <<eNum <<' ' <<eText);
478  eInfo->setErrInfo(eNum, eText);
480  return SFS_ERROR;
481  break;
482  };
483 
484 // Something is quite wrong here
485 //
486  Log.Emsg(epname, "Provider redirect returned no target host name!");
487  eInfo->setErrInfo(ENOMSG, "Server logic error");
489  return SFS_ERROR;
490 }
491 
492 /******************************************************************************/
493 /* r e a d */
494 /******************************************************************************/
495 
497  char *buff, // Out
498  XrdSfsXferSize blen) // In
499 /*
500  Function: Read `blen' bytes at `offset' into 'buff' and return the actual
501  number of bytes read.
502 
503  Input: offset - Contains request information.
504  buff - Address of the buffer in which to place the data.
505  blen - The size of the buffer. This is the maximum number
506  of bytes that will be returned.
507 
508  Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
509 */
510 {
511  static const char *epname = "read";
512  XrdSsiRRInfo rInfo(offset);
514  XrdSfsXferSize retval;
515  unsigned int reqID = rInfo.Id();
516  bool noMore = false;
517 
518 // Find the request object. If not there we may have encountered an eof
519 //
520  if (!(rqstP = rTab.LookUp(reqID)))
521  {if (eofVec.IsSet(reqID))
522  {eofVec.UnSet(reqID);
523  return 0;
524  }
525  return XrdSsiUtils::Emsg(epname, ESRCH, "read", gigID, *eInfo);
526  }
527 
528 // Simply effect the read via the request object
529 //
530  retval = rqstP->Read(noMore, buff, blen);
531 
532 // See if we just completed this request
533 //
534  if (noMore)
535  {rTab.DelFinalize(std::move(rqstP));
536  eofVec.Set(reqID);
537  }
538 
539 // All done
540 //
541  return retval;
542 }
543 
544 /******************************************************************************/
545 /* R e c y c l e */
546 /******************************************************************************/
547 
549 {
550 
551 // Do an immediate reset on ourselves to avoid getting too many locks
552 //
553  Reset();
554 
555 // Get a lock
556 //
557  arMutex.Lock();
558 
559 // Check if we should place this on the free list or simply delete it
560 //
561  if (freeNum < freeMax)
562  {nextFree = freeList;
563  freeList = this;
564  freeNum++;
565  arMutex.UnLock();
566  } else {
567  arMutex.UnLock();
568  delete this;
569  }
570 }
571 
572 /******************************************************************************/
573 /* Private: R e s e t */
574 /******************************************************************************/
575 
576 void XrdSsiFileSess::Reset()
577 {
578 
579 // Close this session
580 //
581  if (isOpen) close(true);
582 
583 // Release other buffers
584 //
585  if (tident) free(tident);
586  if (fsUser) free(fsUser);
587  if (gigID) free(gigID);
588 }
589 
590 /******************************************************************************/
591 /* S e n d D a t a */
592 /******************************************************************************/
593 
595  XrdSfsFileOffset offset,
596  XrdSfsXferSize size)
597 {
598  static const char *epname = "SendData";
599  XrdSsiRRInfo rInfo(offset);
601  unsigned int reqID = rInfo.Id();
602  int rc;
603 
604 // Find the request object
605 //
606  if (!(rqstP = rTab.LookUp(reqID)))
607  return XrdSsiUtils::Emsg(epname, ESRCH, "send", gigID, *eInfo);
608 
609 // Simply effect the send via the request object
610 //
611  rc = rqstP->Send(sfDio, size);
612 
613 // Determine how this ended
614 //
615  if (rc > 0) rc = SFS_OK;
616  else rTab.DelFinalize(std::move(rqstP));
617 
618  return rc;
619 }
620 
621 /******************************************************************************/
622 /* t r u n c a t e */
623 /******************************************************************************/
624 
626 /*
627  Function: Set the length of the file object to 'flen' bytes.
628 
629  Input: flen - The new size of the file.
630 
631  Output: Returns SFS_ERROR a this function is not supported.
632 */
633 {
634  static const char *epname = "trunc";
636  XrdSsiRRInfo rInfo(flen);
637  XrdSsiRRInfo::Opc reqXQ = rInfo.Cmd();
638  unsigned int reqID = rInfo.Id();
639 
640 // Find the request object. If not there we may have encountered an eof
641 //
642  if (!(rqstP = rTab.LookUp(reqID)))
643  {if (eofVec.IsSet(reqID))
644  {eofVec.UnSet(reqID);
645  return 0;
646  }
647  return XrdSsiUtils::Emsg(epname, ESRCH, "cancel", gigID, *eInfo);
648  }
649 
650 // Process request (this can only be a cancel request)
651 //
652  if (reqXQ != XrdSsiRRInfo::Can)
653  return XrdSsiUtils::Emsg(epname, ENOTSUP, "trunc", gigID, *eInfo);
654 
655 // Perform the cancellation
656 //
657  DEBUG(reqID <<':' <<gigID <<" cancelled");
658  rTab.DelFinalize(std::move(rqstP));
659  return SFS_OK;
660 }
661 
662 /******************************************************************************/
663 /* w r i t e */
664 /******************************************************************************/
665 
667  const char *buff, // In
668  XrdSfsXferSize blen) // In
669 /*
670  Function: Write `blen' bytes at `offset' from 'buff' and return the actual
671  number of bytes written.
672 
673  Input: offset - The absolute byte offset at which to start the write.
674  buff - Address of the buffer from which to get the data.
675  blen - The size of the buffer. This is the maximum number
676  of bytes that will be written to 'fd'.
677 
678  Output: Returns the number of bytes written upon success and SFS_ERROR o/w.
679 
680  Notes: An error return may be delayed until the next write(), close(), or
681  sync() call.
682 */
683 {
684  static const char *epname = "write";
685  XrdSsiRRInfo rInfo(offset);
686  unsigned int reqID = rInfo.Id();
687  int reqPass;
688 
689 // Check if we are reading a request segment and handle that. This assumes that
690 // writes to different requests cannot be interleaved (which they can't be).
691 //
692  if (inProg) return writeAdd(buff, blen, reqID);
693 
694 // Make sure this request does not refer to an active request
695 //
696  if (rTab.LookUp(reqID))
697  return XrdSsiUtils::Emsg(epname, EADDRINUSE, "write", gigID, *eInfo);
698 
699 // The offset contains the actual size of the request, make sure it's OK. Note
700 // that it can be zero and by convention the blen must be one if so.
701 //
702  reqPass = reqSize = rInfo.Size();
703  if (reqSize < blen)
704  {if (reqSize || blen != 1)
705  return XrdSsiUtils::Emsg(epname, EPROTO, "write", gigID, *eInfo);
706  reqSize = 1;
707  } else if (reqSize < 0 || reqSize > maxRSZ)
708  return XrdSsiUtils::Emsg(epname, EFBIG, "write", gigID, *eInfo);
709 
710 // Indicate we are in the progress of collecting the request arguments
711 //
712  inProg = true;
713  eofVec.UnSet(reqID);
714 
715 // Do some debugging
716 //
717  DEBUG(reqID <<':' <<gigID <<" rsz=" <<reqSize <<" wsz=" <<blen);
718 
719 // If the complete request is here then grab the buffer, transfer ownership to
720 // the request object, and then activate it for processing.
721 //
722  if (reqSize == blen && xioP)
723  {XrdSfsXioHandle bRef = xioP->Claim(buff, reqSize, minRSZ);
724  if (!bRef)
725  {if (errno) Log.Emsg(epname,"Xio.Claim() failed;",XrdSysE2T(errno));}
726  else {if (!NewRequest(reqID, 0, bRef, reqPass))
727  return XrdSsiUtils::Emsg(epname,ENOMEM,"write xio",gigID,*eInfo);
728  return blen;
729  }
730  }
731 
732 // The full request is not present, so get a buffer to piece it together
733 //
734  if (!(oucBuff = BuffPool->Alloc(reqSize)))
735  return XrdSsiUtils::Emsg(epname, ENOMEM, "write alloc", gigID, *eInfo);
736 
737 // Setup to buffer this
738 //
739  reqLeft = reqSize - blen;
740  memcpy(oucBuff->Data(), buff, blen);
741  if (!reqLeft)
742  {oucBuff->SetLen(reqSize);
743 
744  if (!NewRequest(reqID, oucBuff, 0, reqPass))
745  return XrdSsiUtils::Emsg(epname, ENOMEM, "write sfs", gigID, *eInfo);
746  oucBuff = 0;
747  } else oucBuff->SetLen(blen, blen);
748  return blen;
749 }
750 
751 /******************************************************************************/
752 /* Private: w r i t e A d d */
753 /******************************************************************************/
754 
755 XrdSfsXferSize XrdSsiFileSess::writeAdd(const char *buff, // In
756  XrdSfsXferSize blen, // In
757  unsigned int rid)
758 /*
759  Function: Add `blen' bytes from 'buff' to request and return the actual
760  number of bytes added.
761 
762  Input: buff - Address of the buffer from which to get the data.
763  blen - The size of the buffer. This is the maximum number
764  of bytes that will be added.
765 
766  Output: Returns the number of bytes added upon success and SFS_ERROR o/w.
767 
768  Notes: An error return may be delayed until the next write(), close(), or
769  sync() call.
770 */
771 {
772  static const char *epname = "writeAdd";
773  int dlen;
774 
775 // Make sure the caller is not exceeding the size stated on the first write
776 //
777  if (blen > reqLeft)
778  return XrdSsiUtils::Emsg(epname, EFBIG, "writeAdd", gigID, *eInfo);
779 
780 // Append the bytes
781 //
782  memcpy(oucBuff->Data(dlen), buff, blen);
783 
784 // Adjust how much we have left
785 //
786  reqLeft -= blen;
787  DEBUG(rid <<':' <<gigID <<" rsz=" <<reqLeft <<" wsz=" <<blen);
788 
789 // If we have a complete request. Transfer the buffer ownership to the request
790 // object and activate processing.
791 //
792  if (!reqLeft)
793  {oucBuff->SetLen(reqSize);
794  if (!NewRequest(rid, oucBuff, 0, reqSize))
795  return XrdSsiUtils::Emsg(epname, ENOMEM, "write", gigID, *eInfo);
796  oucBuff = 0;
797  } else {
798  dlen += blen;
799  oucBuff->SetLen(dlen, dlen);
800  }
801 
802 // Return how much we appended
803 //
804  return blen;
805 }
#define tident
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define QTRACE(act)
Definition: XrdCmsTrace.hh:49
#define close(a)
Definition: XrdPosix.hh:48
bool Debug
XrdOucString Path
#define SFS_DATAVEC
#define SFS_ERROR
#define SFS_REDIRECT
#define SFS_STARTED
int XrdSfsFileOpenMode
#define SFS_FCTL_SPEC1
#define SFS_OK
long long XrdSfsFileOffset
int XrdSfsXferSize
class XrdBuffer * XrdSfsXioHandle
Definition: XrdSfsXio.hh:46
#define DUMPIT(x, y)
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
XrdOucBuffer * Alloc(int sz)
void setErrCB(XrdOucEICB *cb, unsigned long long cbarg=0)
int setErrInfo(int code, const char *emsg)
char * getMsgBuff(int &mblen)
void Reset()
Reset object to no message state. Call this method to release appendages.
int setErrCode(int code)
void Bump(int &val)
Definition: XrdOucStats.hh:47
int GetArg() const
const std::string & Get(int &eNum) const
bool WantResponse(XrdOucErrInfo &eInfo)
XrdSfsXferSize Read(bool &done, char *buffer, XrdSfsXferSize blen)
int Send(XrdSfsDio *sfDio, XrdSfsXferSize size)
static XrdSsiFileReq * Alloc(XrdOucErrInfo *eP, XrdSsiFileResource *rP, XrdSsiFileSess *fP, const char *sn, const char *id, unsigned int rnum)
void Activate(XrdOucBuffer *oP, XrdSfsXioHandle bR, int rSz)
int fctl(const int cmd, int alen, const char *args, const XrdSecEntity *client)
int open(const char *fileName, XrdOucEnv &theEnv, XrdSfsFileOpenMode openMode)
int close(bool viaDel=false)
XrdSfsXferSize write(XrdSfsFileOffset fileOffset, const char *buffer, XrdSfsXferSize buffer_size)
bool AttnInfo(XrdOucErrInfo &eInfo, const XrdSsiRespInfo *respP, unsigned int reqID)
XrdSfsXferSize read(XrdSfsFileOffset fileOffset, char *buffer, XrdSfsXferSize buffer_size)
int truncate(XrdSfsFileOffset fileOffset)
int SendData(XrdSfsDio *sfDio, XrdSfsFileOffset offset, XrdSfsXferSize size)
static XrdSsiFileSess * Alloc(XrdOucErrInfo &einfo, const char *user)
void Size(unsigned int sz)
Definition: XrdSsiRRInfo.hh:60
void Cmd(Opc cmd)
Definition: XrdSsiRRInfo.hh:45
void Id(unsigned int id)
Definition: XrdSsiRRInfo.hh:52
static const int MaxDirectXfr
virtual bool Prepare(XrdSsiErrInfo &eInfo, const XrdSsiResource &rDesc)
Prepare for processing subsequent resource request.
long long RspMDBytes
Definition: XrdSsiStats.hh:42
static int Emsg(const char *pfx, int ecode, const char *op, const char *path, XrdOucErrInfo &eDest)
Definition: XrdSsiUtils.cc:159
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdOucEnv theEnv
XrdSsiStats Stats
XrdSsiProvider * Provider
XrdOucBuffPool * BuffPool
XrdSsiService * Service
XrdSysError Log
static const int fullResp
Definition: XrdSsiRRInfo.hh:92
static const int pendResp
Definition: XrdSsiRRInfo.hh:93
int mdlen
Metadata length.
const char * mdata
-> Metadata about response.