43 long long vn,
int opts)
44 : pPLock(0), rPLock(0), wPLock(0),
45 Cache(cP), ioObj(ioP), VNum(vn)
54 SegShft = Cache->SegShft;
55 OffMask = Cache->OffMask;
56 SegSize = Cache->SegSize;
57 maxCache = Cache->maxCache;
62 memset(prRR, -1,
sizeof(prRR) );
63 memset(prBeg, -1,
sizeof(prBeg));
64 memset(prEnd, -1,
sizeof(prEnd));
65 memset(prOpt, 0,
sizeof(prOpt));
72 prOK = (Cache->prNum ? 1 : 0);
74 prAuto = (prOK ?
setAPR(Apr, Cache->aprDefault, SegSize) : 0);
87 {
if (isRW && prOK) pPLock = wPLock = &rwLock;}
88 else if (prOK) rPLock = pPLock = wPLock = &rwLock;
90 rPLock = pPLock = wPLock = &rwLock;
119 delOK = Cache->Detach(ioObj);
129 snprintf(sBuff,
sizeof(sBuff),
130 "Cache: Stats: %lld Read; %lld Get; %lld Pass; "
131 "%lld Write; %lld Put; %lld Hits; %lld Miss; "
132 "%lld pead; %lld HitsPR; %lld MissPR; Path %s\n",
157 MrSw EnforceMrSw(pPLock, pPLopt);
158 long long segBeg, segEnd;
159 int oVal, pVal = 0, rLen, noIO, bPead = 0, prPages = 0;
174 do{
if ((oVal = prOpt[prNext]))
175 {segBeg = prBeg[prNext]; segEnd = prEnd[prNext];
177 if (prNext >= prMax) prNext = 0;
178 if (oVal == prSKIP)
continue;
180 if (Debug > 1) std::cerr <<
"prD: beg " <<(VNum >>XrdRmcReal::Shift) <<
' '
181 <<(segEnd-segBeg+1)*SegSize <<
'@' <<(segBeg*SegSize)
182 <<
" f=" <<
int(oVal) <<
' ' <<ioObj->
Path() <<std::endl;
185 segBeg |= VNum; segEnd |= VNum;
186 do {
if ((cBuff = Cache->Get(ioObj, segBeg, rLen, noIO)))
188 else {pVal = oVal; bPead += rLen; prPages++;}
190 }
while(cBuff && Cache->Ref(cBuff, 0, pVal) && segBeg++ < segEnd);
191 if (Debug > 1) std::cerr <<
"PrD: end " <<(VNum >>XrdRmcReal::Shift)
192 <<
' ' <<prPages <<
" pgs " <<bPead <<std::endl;
196 Statistics.
X.
MissPR += prPages;
208 }
else if (prOpt[prNext])
232 if (prOK && rLen > 0 && Offs > 0
233 && Offs < XrdRmcReal::MaxFO && (Offs + rLen) < XrdRmcReal::MaxFO)
return;
234 QueuePR(Offs>>SegShft, rLen, How);
246 prAuto =
setAPR(Apr, Parms, SegSize);
255 void XrdRmcData::QueuePR(
long long segBeg,
int rLen,
int prHow,
int isAuto)
258 long long segCnt, segEnd;
263 if (Debug) std::cerr <<
"prQ: req " <<rLen <<
'@' <<(segBeg*SegSize) <<std::endl;
268 for (i = 0; i < prRRMax; i++)
if (prRR[i] == segBeg)
return;
272 segCnt = rLen/SegSize + ((rLen & OffMask) != 0);
280 segEnd = segBeg + segCnt - 1;
286 for (i = 0; i < prMax; i++)
287 if (segBeg == prBeg[i] || (segBeg > prBeg[i] && segEnd <= prEnd[i]))
288 {
if (prHow == prSKIP)
289 {
if (Debug) std::cerr <<
"pDQ: " <<rLen <<
'@' <<(segBeg*SegSize) <<std::endl;
297 if (prHow == prSKIP)
return;
301 if (prAuto && prCalc && Statistics.
X.
BytesPead > prCalc)
308 if (Debug) std::cerr <<
"PrD: perf " <<crPerf <<
"% " <<ioObj->
Path() <<std::endl;
311 && (crPerf <= prPerf || crPerf <= prPerf*2))
312 {
if (Debug) std::cerr <<
"PrD: Disabled for " <<ioObj->
Path() <<std::endl;
322 if (prFree == prNext && prOpt[prNext]) prNext = (prNext+1)%prMax;
323 prBeg[prFree] = segBeg; prEnd[prFree] = segEnd;
324 prOpt[prFree++] = prHow;
325 if (prFree >= prMax) prFree = 0;
329 if (Debug) std::cerr <<
"prQ: add " <<rLen <<
'@' <<(segBeg*SegSize) <<std::endl;
330 if (!prActive) {prActive = prWait; Cache->
PreRead(&prReq);}
339 MrSw EnforceMrSw(rPLock, rPLopt);
341 char *cBuff, *Dest = Buff;
342 long long segOff, segNum = (Offs >> SegShft);
343 int noIO, rAmt, rGot, doPR = prAuto, rLeft = rLen;
347 if (rLen <= 0)
return 0;
348 if (XrdRmcReal::MaxFO < Offs || Offs < 0
349 || XrdRmcReal::MaxFO < (Offs + rLen))
return -EOVERFLOW;
355 if (rLen > maxCache) How = prSUSE;
357 QueuePR(segNum, rLen, How);
363 if (rLen > maxCache)
return Read(Now, Buff, Offs, rLen);
369 {
if (rLen >= Apr.
Trigger) doPR = 0;
370 else for (noIO = 0; noIO < prRRMax; noIO++)
371 if (prRR[noIO] == segNum) {doPR = 0;
break;}
374 prRR[prRRNow] = segNum;
375 prRRNow = (prRRNow+1)%prRRMax;
379 if (Debug > 1) std::cerr <<
"Rdr: " <<rLen <<
'@' <<Offs <<
" pr=" <<doPR <<std::endl;
384 segOff = Offs & OffMask;
385 rAmt = SegSize - segOff;
386 if (rAmt > rLen) rAmt = rLen;
390 while((cBuff = Cache->Get(ioObj, segNum, rGot, noIO)))
391 {
if (rGot <= segOff + rAmt) rAmt = (rGot <= segOff ? 0 : rGot-segOff);
392 if (rAmt) {memcpy(Dest, cBuff+segOff, rAmt);
393 Dest += rAmt; Offs += rAmt; Now.
X.
BytesGet += rGot;
397 if (!(Cache->Ref(cBuff, (isFIS ? rAmt : 0)))) {doPR = 0;
break;}
398 segNum++; segOff = 0;
399 if ((rLeft -= rAmt) <= 0)
break;
400 rAmt = (rLeft <= SegSize ? rLeft : SegSize);
410 {EnforceMrSw.UnLock();
411 QueuePR(segNum, rLen, prLRU, 1);
417 if (Debug > 1) std::cerr <<
"Rdr: ret " <<(cBuff ? Dest-Buff : rGot) <<
" hits "
419 return (cBuff ? Dest-Buff : rGot);
425 char *Buff,
long long Offs,
int rLen)
427 char *cBuff, *Dest = Buff;
428 long long segOff, segNum;
429 int noIO, rAmt, rGot, rIO, rPend = 0, rLeft = rLen;
433 segNum = (Offs >> SegShft) | VNum;
434 segOff = Offs & OffMask;
435 rAmt = SegSize - segOff;
436 if (rAmt > rLen) rAmt = rLen;
437 if (Debug > 1) std::cerr <<
"Rdr: " <<rLen <<
'@' <<Offs <<
" pr=" <<prOK <<std::endl;
443 {
if ((rIO = ioObj->
Read(Dest, Offs, rLen)) > 0)
446 }
else if (prOK) QueuePR(Offs >> SegShft, rLen, prSKIP);
451 do{
if ((cBuff = Cache->Get(0, segNum, rGot, noIO)))
453 {
if ((rIO = ioObj->
Read(Dest, Offs, rPend)) < 0)
return rIO;
454 Now.
X.
BytesPass += rIO; Dest += rIO; Offs += rIO; rPend = 0;
456 if (rGot <= segOff + rAmt) rAmt = (rGot <= segOff ? 0 : rGot-segOff);
457 if (rAmt) {memcpy(Dest, cBuff+segOff, rAmt);
458 Dest += rAmt; Offs += rAmt; Now.
X.
Hits++;
462 if (!(Cache->Ref(cBuff, (isFIS ? rAmt : 0))))
break;
463 }
else rPend += rAmt;
465 if ((rLeft -= rAmt) <= 0)
break;
466 rAmt = (rLeft <= SegSize ? rLeft : SegSize);
467 segNum++; segOff = 0;
473 {
if ((rIO = ioObj->
Read(Dest, Offs, rPend)) < 0)
return rIO;
479 if (Debug > 1) std::cerr <<
"Rdr: ret " <<(Dest-Buff) <<
" hits " <<Now.
X.
Hits
480 <<
" pr " <<Now.
X.
HitsPR <<std::endl;
520 if (!isRW)
return -EROFS;
521 if (Offs > XrdRmcReal::MaxFO || Offs < 0)
return -EOVERFLOW;
525 Cache->Trunc(ioObj, (Offs >> SegShft) | VNum);
529 return ioObj->
Trunc(Offs);
540 char *cBuff, *Src = Buff;
541 long long segOff, segNum;
542 int noIO, wAmt, rGot, wLeft = wLen;
546 if (wLen <= 0)
return 0;
547 if (!isRW)
return -EROFS;
548 if (!Buff)
return -EINVAL;
549 if (XrdRmcReal::MaxFO < Offs || Offs < 0
550 || XrdRmcReal::MaxFO < (Offs + wLen))
return -EOVERFLOW;
554 if ((wAmt = ioObj->
Write(Buff, Offs, wLen)) != wLen)
555 return (wAmt < 0 ? wAmt : -EIO);
560 segNum = (Offs >> SegShft) | VNum;
561 segOff = Offs & OffMask;
562 wAmt = SegSize - segOff;
563 if (wAmt > wLen) wAmt = wLen;
567 do{
if (!(cBuff = Cache->Get(0, segNum, rGot, noIO))) Now.
X.
Miss++;
568 else {memcpy(cBuff+segOff, Src, wAmt);
571 Cache->Upd(cBuff, wAmt, segOff);
574 if ((wLeft -= wAmt) <= 0)
break;
575 wAmt = (wLeft <= SegSize ? wLeft : SegSize);
576 segNum++; segOff = 0;
virtual const char * Path()=0
virtual int Read(char *buff, long long offs, int rlen)=0
virtual int Write(char *buff, long long offs, int wlen)=0
static const int SingleUse
Mark pages for single use.
virtual int Trunc(long long offs)=0
void Add(XrdOucCacheStats &S)
struct XrdOucCacheStats::CacheStats X
static const int optRW
File is read/write (o/w read/only)
XrdOucCacheStats Statistics
static const int optFIS
File is structured (e.g. root file)
int Read(char *Buffer, long long Offset, int Length)
int Trunc(long long Offset)
XrdRmcData(XrdRmcReal *cP, XrdOucCacheIO *ioP, long long vn, int opts)
int Write(char *Buffer, long long Offset, int Length)
bool Detach(XrdOucCacheIOCD &iocd)
static int setAPR(aprParms &Dest, aprParms &Src, int pSize)
static const int Serialized
Caller ensures MRSW semantics.
static const int ioMTSafe
CacheIO object is MT-safe.
void Lock(const XrdSysXS_Type usage)
void UnLock(const XrdSysXS_Type usage=xs_None)