XRootD
Loading...
Searching...
No Matches
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
40
42#include "XrdOuc/XrdOucEnv.hh"
44#include "XrdOuc/XrdOucPList.hh"
45
47
48#include "XrdSfs/XrdSfsAio.hh"
49
55#include "XrdSsi/XrdSsiSfs.hh"
56#include "XrdSsi/XrdSsiStats.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
68namespace XrdSsi
69{
70extern XrdOucBuffPool *BuffPool;
71extern XrdSsiProvider *Provider;
73extern XrdSsiStats Stats;
74extern XrdSysError Log;
75extern int respWT;
76extern int minRSZ;
77extern int maxRSZ;
78}
79
80using 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
92namespace
93{
94class nullCallBack : public XrdOucEICB
95{
96public:
97
98void Done(int &Result, XrdOucErrInfo *eInfo, const char *Path=0) {}
99
100int Same(unsigned long long arg1, unsigned long long arg2) {return 0;}
101
102 nullCallBack() {}
103virtual ~nullCallBack() {}
104};
105
106nullCallBack nullCB;
107};
108
109/******************************************************************************/
110/* S t a t i c M e m b e r s */
111/******************************************************************************/
112
113XrdSysMutex XrdSsiFileSess::arMutex;
114XrdSsiFileSess *XrdSsiFileSess::freeList = 0;
115int XrdSsiFileSess::freeNum = 0;
116int XrdSsiFileSess::freeNew = 0;
117int XrdSsiFileSess::freeMax = 100;
118int XrdSsiFileSess::freeAbs = 200;
119
120bool XrdSsiFileSess::authDNS = false;
121
122/******************************************************************************/
123/* A l l o c */
124/******************************************************************************/
125
126XrdSsiFileSess *XrdSsiFileSess::Alloc(XrdOucErrInfo &einfo, const char *user)
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
250int 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
293int 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");
331 Stats.Bump(Stats.RspReady);
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, "");
342 Stats.Bump(Stats.RspUnRdy);
343 return SFS_STARTED;
344}
345
346/******************************************************************************/
347/* Private: I n i t */
348/******************************************************************************/
349
350void 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
372bool XrdSsiFileSess::NewRequest(unsigned int reqid,
373 XrdOucBuffer *oP,
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
403int 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";
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);
463 Stats.Bump(Stats.ReqRedir);
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);
472 Stats.Bump(Stats.ReqStalls);
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);
479 Stats.Bump(Stats.ReqPrepErrs);
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");
488 Stats.Bump(Stats.ReqPrepErrs);
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
576void 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
755XrdSfsXferSize 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)
#define EPNAME(x)
#define QTRACE(act)
#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
char * Data() const
void SetLen(int dataL, int dataO=0)
void Reset()
Definition XrdSsiBVec.hh:55
static XrdSsiFileReq * Alloc(XrdOucErrInfo *eP, XrdSsiFileResource *rP, XrdSsiFileSess *fP, const char *sn, const char *id, unsigned int rnum)
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)
XrdOucErrInfo * errInfo()
int SendData(XrdSfsDio *sfDio, XrdSfsFileOffset offset, XrdSfsXferSize size)
static XrdSsiFileSess * Alloc(XrdOucErrInfo &einfo, const char *user)
void Size(unsigned int sz)
void Cmd(Opc cmd)
void Id(unsigned int id)
static const int MaxDirectXfr
static int Emsg(const char *pfx, int ecode, const char *op, const char *path, XrdOucErrInfo &eDest)
XrdSsiStats Stats
XrdSsiProvider * Provider
XrdOucBuffPool * BuffPool
XrdSsiService * Service
XrdSysError Log
static const int fullResp
static const int pendResp
int mdlen
Metadata length.
const char * mdata
-> Metadata about response.