XRootD
XrdXrootdXeqPgrw.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d X r o o t d X e q P g r w . c c */
4 /* */
5 /* (c) 2020 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 <cctype>
31 #include <cstdio>
32 #include <sys/uio.h>
33 
35 #include "XrdSys/XrdSysPlatform.hh"
36 
37 #include "XProtocol/XProtocol.hh"
38 
39 #include "Xrd/XrdBuffer.hh"
40 #include "Xrd/XrdLink.hh"
41 #include "XrdOuc/XrdOucCRC.hh"
42 #include "XrdOuc/XrdOucString.hh"
55 
56 /******************************************************************************/
57 /* G l o b a l s */
58 /******************************************************************************/
59 
61 
62 namespace
63 {
64 static const int pgPageSize = XrdProto::kXR_pgPageSZ;
65 static const int pgPageMask = XrdProto::kXR_pgPageSZ-1;
66 static const int pgUnitSize = XrdProto::kXR_pgUnitSZ;
67 }
68 
69 namespace
70 {
71 static const int pgAioMin = XrdXrootdPgrwAio::aioSZ
72  + XrdXrootdPgrwAio::aioSZ*8/10; // 1.8 of aiosz
73 static const int pgAioHalf= XrdXrootdPgrwAio::aioSZ/2;
74 }
75 
76 /******************************************************************************/
77 /* d o _ P g C l o s e */
78 /******************************************************************************/
79 
80 bool XrdXrootdProtocol::do_PgClose(XrdXrootdFile *fP, int &rc)
81 {
82  XrdXrootdPgwFob *fobP = fP->pgwFob;
83  int numErrs, numFixes, numLeft;
84 
85 // Make sure we have a fob
86 //
87  if (!fobP) return true;
88 
89 // Obtain the checksum status of this file and update statistics
90 //
91  numLeft = fobP->numOffs(&numErrs, &numFixes);
92  fP->Stats.pgUpdt(numErrs, numFixes, numLeft);
93 
94 // If there are uncorrected checksum, indicate failure. These will be logged
95 // when the fob is deleted later on.
96 //
97  if (numLeft)
98  {char ebuff[128];
99  snprintf(ebuff,sizeof(ebuff),"%d uncorrected checksum errors",numLeft);
100  rc = Response.Send(kXR_ChkSumErr, ebuff);
101  return false;
102  }
103 
104 // All is well
105 //
106  return true;
107 }
108 
109 /******************************************************************************/
110 /* d o _ P g R e a d */
111 /******************************************************************************/
112 
113 int XrdXrootdProtocol::do_PgRead()
114 {
115  int pathID;
117  numReads++;
118 
119 // Unmarshall the data
120 //
121  IO.IOLen = ntohl(Request.pgread.rlen);
122  n2hll(Request.pgread.offset, IO.Offset);
123 
124 // Perform a sanity check on the length
125 //
126  if (IO.IOLen <= 0)
127  return Response.Send(kXR_ArgInvalid, "Read length is invalid");
128 
129 // Find the file object
130 //
131  if (!FTab || !(IO.File = FTab->Get(fh.handle)))
133  "pgread does not refer to an open file");
134 
135 // Now handle the optional pathid and reqflags arguments.
136 //
137  IO.Flags = 0;
138  if (!Request.header.dlen) pathID = 0;
140  pathID = static_cast<int>(rargs->pathid);
141  if (Request.header.dlen > 1)
142  IO.Flags = static_cast<unsigned short>(rargs->reqflags);
143  }
144 
145 // Trace this
146 //
147  TRACEP(FSIO,pathID<<" pgread "<<IO.IOLen<<'@'<<IO.Offset
148  <<" fn=" <<IO.File->FileKey);
149 
150 // If we are monitoring, insert a read entry
151 //
152  if (Monitor.InOut())
155 
156 // Do statistics. They will not always be accurate because we may not be
157 // able to fully complete the I/O from the file. Note that we also count
158 // the checksums which a questionable practice.
159 //
161 
162 // Use synchronous reads unless async I/O is allowed, the read size is
163 // sufficient, and there are not too many async operations in flight.
164 //
165  if (IO.File->AsyncMode && IO.IOLen >= pgAioMin
166  && IO.Offset+IO.IOLen <= IO.File->Stats.fSize+pgAioHalf
169  {XrdXrootdProtocol *pP;
170  XrdXrootdPgrwAio *aioP;
171  int rc;
172 
173  if (!pathID) pP = this;
174  else {if (!(pP = VerifyStream(rc, pathID, false))) return rc;
175  if (pP->linkAioReq >= as_maxperlnk) pP = 0;
176  }
177 
178  if (pP && (aioP = XrdXrootdPgrwAio::Alloc(pP, pP->Response, IO.File)))
179  {if (!IO.File->aioFob) IO.File->aioFob = new XrdXrootdAioFob;
180  aioP->Read(IO.Offset, IO.IOLen);
181  return 0;
182  }
183  SI->AsyncRej++;
184  }
185 
186 // See if an alternate path is required, offload the read
187 //
188  if (pathID) return do_Offload(&XrdXrootdProtocol::do_PgRIO, pathID);
189 
190 // Now do the read on the main path
191 //
192  return do_PgRIO();
193 }
194 
195 /******************************************************************************/
196 /* d o _ P g R I O */
197 /******************************************************************************/
198 
199 // IO.File = file to be read
200 // IO.Offset = Offset at which to read
201 // IO.IOLen = Number of bytes to read from file and write to socket
202 
203 int XrdXrootdProtocol::do_PgRIO()
204 {
205 // We restrict the maximum transfer size to generate no more than 1023 iovec
206 // elements where the first is used for the header.
207 //
208  static const int maxIOVZ = XrdSys::getIovMax();
209  static const int maxCSSZ = maxIOVZ/2 - 1;
210  static const int maxPGRD = maxCSSZ*pgPageSize; // 2,093,056 usually
211  static const int infoLen = sizeof(kXR_int64);
212 
213  struct pgReadResponse
215  kXR_int64 ofs;
216  } pgrResp;
217 
218  XrdSfsFile *sfsP = IO.File->XrdSfsp;
219  uint64_t pgrOpts = 0;
220  int dlen, fLen, lLen, rc, xframt, Quantum;
221  uint32_t csVec[maxCSSZ];
222  struct iovec iov[maxIOVZ];
223 
224 // Set flags, as needed
225 //
227 
228 // Preinitialize the header
229 //
230  pgrResp.rsp.bdy.requestid = kXR_pgread - kXR_1stRequest;
231  pgrResp.rsp.bdy.resptype = XrdProto::kXR_PartialResult;;
232  memset(pgrResp.rsp.bdy.reserved, 0, sizeof(pgrResp.rsp.bdy.reserved));
233 
234 // Calculate the total pages in the read request. Note that the first and
235 // last pages may require short reads if they are not fully aligned.
236 //
237  int pgOff, rPages, rLen = IO.IOLen;
238  rPages = XrdOucPgrwUtils::csNum(IO.Offset, IO.IOLen) * pgPageSize;
239 
240 // Compute the quantum.
241 //
242  Quantum = (maxPGRD > maxBuffsz ? maxBuffsz : maxPGRD);
243  if (rPages < Quantum) Quantum = rPages;
244 
245 // Make sure we have a large enough buffer. We may need to adjust it downward
246 // due to reallocation rounding.
247 //
248  if (!argp || Quantum < halfBSize || Quantum > argp->bsize)
249  {if ((rc = getBuff(1, Quantum)) <= 0) return rc;}
250  else if (hcNow < hcNext) hcNow++;
251  if (argp->bsize > maxPGRD) Quantum = maxPGRD;
252 
253 // Compute the number of iovec elements we need plus one for the header. The
254 // Quantum is gauranteed to be a multiple of pagesize now. Verify that this
255 // calculation was indeed correct to avoid overwriting the stack.
256 //
257  int items = Quantum / pgPageSize;
258  if (items > maxCSSZ)
259  return Response.Send(kXR_Impossible, "pgread logic error 1");
260 
261 // Preinitialize the io vector for checksums and data (leave 1st element free).
262 //
263  uint32_t *csVP = csVec;
264  char *buff = argp->buff;
265  int i = 1, n = items * 2;
266  while(i < n)
267  {iov[i ].iov_base = csVP++;
268  iov[i++].iov_len = sizeof(uint32_t);
269  iov[i ].iov_base = buff;
270  iov[i++].iov_len = pgPageSize;
271  buff += pgPageSize;
272  }
273 
274 // If this is an unaligned read, offset the unaligned segment in the buffer
275 // so that remaining pages are page-aligned. It will be reset when needed.
276 // We also calculate the actual length of the first read.
277 //
278  if ((pgOff = IO.Offset & pgPageMask))
279  {rLen = pgPageSize - pgOff;
280  buff = argp->buff + pgOff;
281  iov[2].iov_base = buff;
282  iov[2].iov_len = rLen;
283  rLen += Quantum - pgPageSize;
284  } else {
285  rLen = Quantum;
286  buff = argp->buff;
287  }
288  if (IO.IOLen < rLen) rLen = IO.IOLen;
289 
290 // Now read all of the data. For each read we must recacalculate the number
291 // of iovec elements that we will use to send the data as fewer bytes may have
292 // been read. In fact, no bytes may have been read.
293 //
294  long long ioOffset = IO.Offset;
295  do {if ((xframt = sfsP->pgRead(IO.Offset, buff, rLen, csVec, pgrOpts)) <= 0)
296  break;
297 
298  items = XrdOucPgrwUtils::csNum(IO.Offset, xframt, fLen, lLen);
299  iov[2].iov_len = fLen;
300  if (items > 1) iov[items<<1].iov_len = lLen;
301 
302  if (xframt < rLen || xframt == IO.IOLen)
303  {pgrResp.rsp.bdy.resptype = XrdProto::kXR_FinalResult;
304  IO.IOLen = 0;
305  } else {
306  IO.IOLen -= xframt; IO.Offset += xframt;
307  rLen = (IO.IOLen < Quantum ? IO.IOLen : Quantum);
308  }
309 
310  for (int i = 0; i < items; i++) csVec[i] = htonl(csVec[i]);
311 
312  pgrResp.ofs = htonll(ioOffset);
313 // char trBuff[512];
314 // snprintf(trBuff, sizeof(trBuff), "Xeq PGR: %d@%lld (%lld)\n",
315 // xframt, ioOffset, ioOffset>>12);
316 // std::cerr<<trBuff<<std::flush;
317  dlen = xframt + (items * sizeof(uint32_t));
318  if ((rc = Response.Send(pgrResp.rsp, infoLen, iov, items*2+1, dlen)) < 0)
319  return rc;
320 
321  if (pgOff)
322  {iov[2].iov_base = argp->buff;
323  iov[2].iov_len = pgPageSize;
324  buff = argp->buff;
325  pgOff = 0;
326  }
327 
328  ioOffset = IO.Offset;
329  } while(IO.IOLen > 0);
330 
331 // Determine why we ended here
332 //
333  if (xframt < 0) return fsError(xframt, 0, sfsP->error, 0, 0);
334 
335 // Return no bytes if we were tricked into sending a partial result
336 //
337  if (pgrResp.rsp.bdy.resptype != XrdProto::kXR_FinalResult)
338  {pgrResp.rsp.bdy.resptype = XrdProto::kXR_FinalResult;
339  pgrResp.rsp.bdy.dlen = 0;
340  pgrResp.ofs = htonll(IO.Offset);
341  return Response.Send(pgrResp.rsp, infoLen);
342  }
343  return 0;
344 }
345 
346 /******************************************************************************/
347 /* d o _ P g W r i t e */
348 /******************************************************************************/
349 
350 int XrdXrootdProtocol::do_PgWrite()
351 {
353  int pathID;
354  numWrites++;
355 
356 // Unmarshall the data
357 //
359  n2hll(Request.pgwrite.offset, IO.Offset);
360  pathID = Request.pgwrite.pathid;
361  IO.Flags = static_cast<unsigned short>(Request.pgwrite.reqflags);
362 
363 // Perform a sanity check on the length.
364 //
365  if (IO.IOLen <= (int)sizeof(kXR_unt32))
366  {Response.Send(kXR_ArgInvalid, "pgwrite length is invalid");
367  return Link->setEtext("pgwrite protocol violation");
368  }
369 
370 // Validate pathid, at least as much as we need to. If it's wrong then we
371 // don't know where the data is and we just let it go.
372 //
373  if (pathID && (pathID >= maxStreams || !Stream[pathID]))
374  return Response.Send(kXR_ArgInvalid, "invalid path ID");
375 
376 // Find the file object
377 //
378  if (!FTab || !(IO.File = FTab->Get(fh.handle)))
379  {IO.File = 0;
380  return do_WriteNone(pathID);
381  }
382 
383 // If the file object does not have a pgWrite object, allocate one.
384 //
385  if (IO.File->pgwFob == 0) IO.File->pgwFob = new XrdXrootdPgwFob(IO.File);
386 
387 // Trace this
388 //
389  TRACEP(FSIO, pathID<<" pgwrite "
390  <<(IO.Flags & XrdProto::kXR_pgRetry ? "retry " : "")
391  <<IO.IOLen<<'@'<<IO.Offset<<" fn=" <<IO.File->FileKey);
392 
393 // Do statistics. They will not always be accurate because we may not be
394 // able to fully complete the I/O to the file. Note that we also count
395 // the checksums which a questionable practice.
396 //
398 
399 // If we are monitoring, insert a write entry
400 //
401  if (Monitor.InOut())
404 
405 // See if an alternate path is required, offload the write
406 //
407  if (pathID) return do_Offload(&XrdXrootdProtocol::do_PgWIO, pathID);
408 
409 // Now do the write on the main path
410 //
411  return do_PgWIO(true);
412 }
413 
414 /******************************************************************************/
415 /* d o _ P g W A I O */
416 /******************************************************************************/
417 
418 // IO.File = file to be written
419 // IO.Offset = Offset at which to write
420 // IO.IOLen = Number of bytes to read from socket
421 // IO.Flags = Flags associated with request
422 
423 bool XrdXrootdProtocol::do_PgWAIO(int &rc)
424 {
425  XrdXrootdPgrwAio *aioP;
426 
427 // Make sure the client is fast enough to do this
428 //
429  if (myStalls >= as_maxstalls)
430  {SI->AsyncRej++;
431  myStalls--;
432  return false;
433  }
434 
435 // Allocate an aio request object
436 //
437  if (!(aioP = XrdXrootdPgrwAio::Alloc(this, Response, IO.File, pgwCtl)))
438  {SI->AsyncRej++;
439  return false;
440  }
441 
442 // Issue the write request
443 //
444  rc = aioP->Write(IO.Offset, IO.IOLen);
445  return true;
446 }
447 
448 /******************************************************************************/
449 /* d o _ P g W I O */
450 /******************************************************************************/
451 
452 // IO.File = file to be written
453 // IO.Offset = Offset at which to write
454 // IO.IOLen = Number of bytes to read from socket
455 // IO.Flags = Flags associated with request
456 
457 int XrdXrootdProtocol::do_PgWIO() {return do_PgWIO(true);}
458 
459 int XrdXrootdProtocol::do_PgWIO(bool isFresh)
460 {
461  struct iovec *ioV;
462  XrdSfsFile *sfsP = IO.File->XrdSfsp;
463  const char *eMsg;
464  char *buff;
465  kXR_unt32 *csVec;
466  int n, rc, Quantum, iovLen, iovNum, csNum;
467  bool isRetry = (IO.Flags & XrdProto::kXR_pgRetry) != 0;
468 
469 // Verify that we still have a control area and allocate a control object
470 // if we do not have one already. The object stays around until disconnect.
471 //
472  if (!IO.File->pgwFob)
473  return do_WriteNone(PathID, kXR_Impossible, "pgwrite logic error 1");
474  if (!pgwCtl) pgwCtl = new XrdXrootdPgwCtl(PathID);
475 
476 // If this is the first entry then check if the request is eligible for async
477 // I/O or if this is a retry request which, of course, is not eligible.
478 //
479  if (isFresh)
480  {if (IO.File->AsyncMode && IO.IOLen >= pgAioMin
482  && !isRetry && do_PgWAIO(rc)) return rc;
483  if (isRetry && !do_PgWIORetry(rc)) return rc;
484  if (!do_PgWIOSetup(pgwCtl)) return -1;
485  }
486 
487 // Either complete the current frame or start a new one. When we start a new
488 // one, the I/O will not return unless all of the data was successfully read.
489 // Hence, we update the length outstanding.
490 //
491 do{if (isFresh)
492  {if (!(ioV = pgwCtl->FrameInfo(iovNum, iovLen))) break;
493  IO.IOLen -= iovLen;
494  if ((rc = getData(this, "pgwrite", ioV, iovNum))) return rc;
495  }
496 
497 // We now have all the data, get checksum and data information
498 //
499  if (!(csVec = pgwCtl->FrameInfo(csNum, buff, Quantum, argp)))
500  return do_WriteNone(PathID, kXR_Impossible, "pgwrite logic error 2");
501 
502 // Convert checksums to host byte order
503 //
504  for (int i = 0; i < csNum; i++) csVec[i] = ntohl(csVec[i]);
505 
506 // Verify the checksums
507 //
508  XrdOucPgrwUtils::dataInfo dInfo(buff, csVec, IO.Offset, Quantum);
509  off_t bado;
510  int badc;
511  bool aOK = true;
512 
513  while(dInfo.count > 0 && !XrdOucPgrwUtils::csVer(dInfo, bado, badc))
514  {if ((eMsg = pgwCtl->boAdd(IO.File, bado, badc)))
515  return do_WriteNone(PathID, kXR_TooManyErrs, eMsg);
516  aOK = false;
517  }
518 
519 // Write the data out. The callee is responsible for unaligned writes!
520 //
521  if ((rc = sfsP->pgWrite(IO.Offset, buff, Quantum, csVec)) <= 0)
522  {IO.EInfo[0] = rc; IO.EInfo[1] = 0;
523  return do_WriteNone();
524  }
525 
526 // If this was a successful retry write, remove corrrected offset
527 //
528  if (aOK && IO.Flags & XrdProto::kXR_pgRetry)
529  IO.File->pgwFob->delOffs(IO.Offset, Quantum);
530 
531 // Update offset and advance to next frame
532 //
533  IO.Offset += Quantum;
534  isFresh = true;
535 
536  } while(pgwCtl->Advance());
537 
538 
539 // Return final result
540 //
541  buff = pgwCtl->boInfo(n);
542  return Response.Send(pgwCtl->resp, sizeof(pgwCtl->info), buff, n);
543 }
544 
545 /******************************************************************************/
546 /* d o _ P g W I O R e t r y */
547 /******************************************************************************/
548 
549 // IO.File = file to be written
550 // IO.Offset = Offset at which to write
551 // IO.IOLen = Number of bytes to read from socket
552 // IO.Flags = Flags associated with request
553 
554 bool XrdXrootdProtocol::do_PgWIORetry(int &rc)
555 {
556  static const int csLen = sizeof(kXR_unt32);
557  bool isBad;
558 
559 // Make sure the write does not cross a page bounday. For unaligned writes we
560 // can compute the exact length that we need. Otherwise, it can't be bigger
561 // than a unit's worth of data. Not precise but usually good enough.
562 //
563  if (IO.Offset & pgPageMask)
564  {int n = pgPageSize - (IO.Offset & pgPageMask);
565  isBad = IO.IOLen > (n + csLen);
566  } else isBad = IO.IOLen > pgUnitSize;
567 
568 // Deep six the write if it violates retry rules.
569 //
570  if (isBad)
571  {rc = do_WriteNone(PathID, kXR_ArgInvalid,
572  "pgwrite retry of more than one page not allowed");
573  return false;
574  }
575 
576 // Make sure that the offset is registered, if it is not, treat this as a
577 // regular write as this may have been a resend during write recovery.
578 //
579  if (!IO.File->pgwFob->hasOffs(IO.Offset, IO.IOLen - csLen))
580  {char buff[64];
581  snprintf(buff, sizeof(buff), "retry %d@%lld", IO.IOLen-csLen, IO.Offset);
582  eDest.Emsg("pgwRetry", buff, "not in error; fn=", IO.File->FileKey);
584  }
585 
586 // We can proceed with this write now.
587 //
588  return true;
589 }
590 
591 /******************************************************************************/
592 /* d o _ P g w I O S e t u p */
593 /******************************************************************************/
594 
595 // IO.File = file to be written
596 // IO.Offset = Offset at which to write
597 // IO.IOLen = Number of bytes to read from socket
598 // IO.Flags = Flags associated with request
599 
600 bool XrdXrootdProtocol::do_PgWIOSetup(XrdXrootdPgwCtl *pgwCtl)
601 {
602  const char *eMsg;
603  int Quantum;
604 
605 // Compute the minimum (4K) or maximum buffer size we will use.
606 //
608  Quantum = (IO.IOLen < pgPageSize ? pgPageSize : IO.IOLen);
609  else Quantum = XrdXrootdPgwCtl::maxBSize;
610 
611 // Make sure we have a large enough buffer
612 //
613  if (!argp || Quantum < halfBSize || argp->bsize < Quantum
615  {if (getBuff(0, Quantum) <= 0) return -1;}
616  else if (hcNow < hcNext) hcNow++;
617 
618 // Do the setup. If it fails then either the client sent an incorrect stream
619 // of the header was corrupted. In either case, it doesn't matter as we can't
620 // depend on the information to clear the stream. So, we close the connection.
621 //
622  if ((eMsg = pgwCtl->Setup(argp, IO.Offset, IO.IOLen)))
624  Link->setEtext("pgwrite protocol violation");
625  return false;
626  }
627  return true;
628 }
@ kXR_ArgInvalid
Definition: XProtocol.hh:990
@ kXR_Impossible
Definition: XProtocol.hh:1021
@ kXR_TooManyErrs
Definition: XProtocol.hh:1023
@ kXR_ChkSumErr
Definition: XProtocol.hh:1009
@ kXR_FileNotOpen
Definition: XProtocol.hh:994
kXR_char fhandle[4]
Definition: XProtocol.hh:531
struct ClientPgReadRequest pgread
Definition: XProtocol.hh:861
struct ClientPgWriteRequest pgwrite
Definition: XProtocol.hh:862
struct ClientRequestHdr header
Definition: XProtocol.hh:846
kXR_char fhandle[4]
Definition: XProtocol.hh:509
@ kXR_1stRequest
Definition: XProtocol.hh:111
@ kXR_pgread
Definition: XProtocol.hh:142
kXR_int32 dlen
Definition: XProtocol.hh:159
long long kXR_int64
Definition: XPtypes.hh:98
unsigned int kXR_unt32
Definition: XPtypes.hh:90
#define eMsg(x)
#define TRACEP(act, x)
XrdSysTrace XrdXrootdTrace
int bsize
Definition: XrdBuffer.hh:46
char * buff
Definition: XrdBuffer.hh:45
static bool csVer(dataInfo &dInfo, off_t &bado, int &badc)
static int csNum(off_t offs, int count)
Compute the required size of a checksum vector based on offset & length.
static const uint64_t Verify
Options for pgRead() and pgWrite() as noted below.
XrdOucErrInfo & error
virtual XrdSfsXferSize pgRead(XrdSfsFileOffset offset, char *buffer, XrdSfsXferSize rdlen, uint32_t *csvec, uint64_t opts=0)
virtual XrdSfsXferSize pgWrite(XrdSfsFileOffset offset, char *buffer, XrdSfsXferSize wrlen, uint32_t *csvec, uint64_t opts=0)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
void pgrOps(int rsz, bool isRetry=false)
void pgwOps(int wsz, bool isRetry=false)
void pgUpdt(int wErrs, int wFixd, int wUnc)
XrdXrootdFile * Get(int fnum)
XrdXrootdPgwFob * pgwFob
XrdSfsFile * XrdSfsp
XrdXrootdAioFob * aioFob
XrdXrootdFileStats Stats
XrdXrootdMonitor * Agent
void Add_rd(kXR_unt32 dictid, kXR_int32 rlen, kXR_int64 offset)
void Add_wr(kXR_unt32 dictid, kXR_int32 wlen, kXR_int64 offset)
static const int aioSZ
void Read(long long offs, int dlen) override
static XrdXrootdPgrwAio * Alloc(XrdXrootdProtocol *protP, XrdXrootdResponse &resp, XrdXrootdFile *fP, XrdXrootdPgwBadCS *bcsP=0)
int Write(long long offs, int dlen) override
const char * boAdd(XrdXrootdFile *fP, kXR_int64 foffs, int dlen=XrdProto::kXR_pgPageSZ)
char * boInfo(int &boLen)
ServerResponseStatus resp
static const int maxBSize
struct iovec * FrameInfo(int &iovn, int &rdlen)
const char * Setup(XrdBuffer *buffP, kXR_int64 fOffs, int totlen)
ServerResponseBody_pgWrite info
bool hasOffs(kXR_int64 foffs, int dlen)
bool delOffs(kXR_int64 foffs, int dlen)
int numOffs(int *errs=0, int *fixs=0)
static XrdXrootdStats * SI
XrdXrootdProtocol * VerifyStream(int &rc, int pID, bool lok=true)
XrdXrootdProtocol * Stream[maxStreams]
XrdXrootd::IOParms IO
XrdXrootdPgwCtl * pgwCtl
XrdXrootdFileTable * FTab
static XrdSysError & eDest
int getData(gdCallBack *gdcbP, const char *dtype, char *buff, int blen)
XrdXrootdMonitor::User Monitor
XrdXrootdResponse Response
static const int maxStreams
static RAtomic_int srvrAioOps
long long AsyncRej
static const int kXR_pgUnitSZ
Definition: XProtocol.hh:496
static const int kXR_pgPageSZ
Definition: XProtocol.hh:494
@ kXR_PartialResult
Definition: XProtocol.hh:1250
@ kXR_FinalResult
Definition: XProtocol.hh:1249
static const int kXR_pgRetry
Definition: XProtocol.hh:503
int getIovMax()
XrdXrootdFile * File