37 #include <sys/types.h>
44 #define MAP_ANONYMOUS MAP_ANON
61 Slots(0), Slash(0), Base((char *)MAP_FAILED),
Dbg(0), Lgs(0),
62 AZero(0), Attached(0), prFirst(0), prLast(0),
63 prReady(0), prStop(0), prNum(0)
78 if (ParmV.
MaxFiles <= 0) maxFiles = (isServ ? 16384 : 256);
80 maxFiles = maxFiles/
sizeof(int)*
sizeof(
int);
81 if (!maxFiles) maxFiles = 256;
86 if (ParmV.
PageSize <= 0) SegSize = 32768;
87 else if (!(SegSize = ParmV.
PageSize & ~0xfff)) SegSize = 4096;
89 SegShft = 0; n = SegSize-1;
90 while(n) {SegShft++; n = n >> 1;}
97 if (SegCnt < minPag) SegCnt = minPag;
98 if (ParmV.
Max2Cache < SegSize) maxCache = SegSize;
99 else maxCache = ParmV.
Max2Cache/SegSize*SegSize;
104 Bytes =
static_cast<size_t>(SegSize)*SegCnt;
105 Base = (
char *)mmap(0, Bytes + SegCnt*
sizeof(
int), PROT_READ|PROT_WRITE,
106 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
107 if (Base == MAP_FAILED) {rc = errno;
return;}
108 Slash = (
int *)(Base + Bytes); HNum = SegCnt/2*2-1;
113 if (!(Slots =
new XrdRmcSlot[SegCnt+maxFiles]))
return;
120 hMax = SegSize/
sizeof(int);
121 sBeg = sFree = SegCnt;
122 sEnd = SegCnt + maxFiles;
126 for (n = sBeg; n < sEnd; n++)
128 Slots[n].
HLink = n+1;
130 Slots[sEnd-1].
HLink = 0;
139 0,
"Prereader"))
break;
181 delete Slots; Slots = 0;
185 if (Base != MAP_FAILED)
186 {munmap(Base,
static_cast<size_t>(SegSize)*SegCnt);
187 Base = (
char *)(MAP_FAILED);
205 int Cnt, Fnum = 0, theOpts =
Opts &
optRW;
209 if (AZero) {errno = ECANCELED;
return ioP;}
217 if (!(Cnt = ioAdd(ioP, Fnum)))
226 else {
long long vNum =
static_cast<long long>(Fnum-SegCnt) << Shift
227 | (
static_cast<long long>(Inst) << (Shift - 16));
228 Inst = (Inst+1) & 0xffff;
229 if ((dP =
new XrdRmcData(
this, ioP, vNum, theOpts)))
235 if (Dbg) std::cerr <<
"Cache: Attached " <<Cnt <<
'/' <<Attached <<
' '
240 if (!dP) {errno = ENOMEM;
return ioP;}
252 int sNum, Fnum, Free = 0, Faults = 0;
256 sNum = ioDel(ioP, Fnum);
257 if (!sNum || sNum > 1)
return 0;
266 else {sP->
Hide(Slots, Slash, sP->Contents%HNum);
276 if (AZero && Attached <= 0) AZero->
Post();
280 if (Dbg) std::cerr <<
"Cache: " <<Attached <<
" att; rel " <<Free <<
" slots; "
282 <<ioP->
Path() <<std::endl;
293 void XrdRmcReal::eMsg(
const char *
Path,
const char *What,
long long xOff,
299 {sprintf(Buff,
"Cache: Error %d %s %d bytes at %lld; path=",
300 eCode, What, xAmt, xOff);
301 std::cerr <<Buff <<
Path <<std::endl;
309 char *XrdRmcReal::Get(
XrdOucCacheIO *ioP,
long long lAddr,
int &rAmt,
int &noIO)
314 int nUse, Fnum, Slot, segHash = lAddr%HNum;
328 if (Dbg > 1) std::cerr <<
"Cache: Wait slot " <<Slot <<std::endl;
330 if (sP->Contents != lAddr) {rAmt = -EIO;
return 0;}
338 if (Dbg > 2) std::cerr <<
"Cache: Hit slot " <<Slot <<
" sz " <<rAmt <<
" nio "
340 return Base+(
static_cast<long long>(Slot)*SegSize);
346 if (!ioP || !(Slot = Slots[Slots->
Status.
LRU.
Next].Pull(Slots)))
347 {rAmt = -ENOMEM;
return 0;}
352 if (sP->Contents >= 0)
354 sP->
Hide(Slots, Slash, sP->Contents%HNum);
362 cBuff = Base+(
static_cast<long long>(Slot)*SegSize);
363 rAmt = ioP->
Read(cBuff, (lAddr & Strip) << SegShft, SegSize);
380 {sP->Contents = lAddr;
381 sP->
HLink = Slash[segHash];
382 Slash[segHash] = Slot;
383 Fnum = (lAddr >> Shift) + SegCnt;
384 Slots[Fnum].
Owner(Slots, sP);
387 if (Dbg > 2) std::cerr <<
"Cache: Miss slot " <<Slot <<
" sz "
390 eMsg(ioP->
Path(),
"reading", (lAddr & Strip) << SegShft, SegSize, rAmt);
407 int hip, phip, hent = ioEnt(KeyVal);
411 if ((hip = hTab[hent]) && (hip = ioLookup(phip, hip, KeyVal)))
412 {iNum = hip;
return ++Slots[hip].
Count;}
417 {sFree = Slots[sFree].
HLink;
418 Slots[hip].
File(KeyVal, hTab[hent]);
425 return (hip ? 1 : 0);
434 int cnt, hip, phip, hent = ioEnt(KeyVal);
438 if (!(hip = hTab[hent]) || !(hip = ioLookup(phip, hip, KeyVal)))
return 0;
443 cnt = --(Slots[hip].
Count);
445 {
if (phip) Slots[phip].
HLink = Slots[hip].
HLink;
446 else hTab[hent] = Slots[hip].
HLink;
447 Slots[hip].
HLink = sFree; sFree = hip;
449 return (cnt < 0 ? 1 : cnt+1);
462 if (Dbg) std::cerr <<
"Cache: preread thread started; now " <<prNum <<std::endl;
468 {
if (!(prFirst = prP->Next)) prLast = 0;
470 prP->Data->Preread();
477 if (prNum > 0) prReady.
Post();
479 if (Dbg) std::cerr <<
"Cache: preread thread exited; left " <<prNum <<std::endl;
491 if (prLast) {prLast->Next = prReq; prLast = prReq;}
492 else prLast = prFirst = prReq;
505 int XrdRmcReal::Ref(
char *Addr,
int rAmt,
int sFlags)
507 XrdRmcSlot *sP = &Slots[(Addr-Base)>>SegShft];
513 if (sP->Contents >= 0)
514 {
if (sP->
Count < 0) eof = 1;
517 {
if (sFlags) sP->
Count |= sFlags;
518 else if (!eof && (sP->
Count -= rAmt) < 0) sP->
Count = 0;
520 if (sFlags) {sP->
Count |= sFlags; sP->
reRef(Slots);}
523 else if (eof || (sP->
Count -= rAmt) > 0) sP->
reRef(Slots);
524 else {sP->
Count = SegSize/2; sP->
unRef(Slots);}
532 <<
" slot " <<((Addr-Base)>>SegShft)
547 int sNum, Free = 0, Left = 0, Fnum = (lAddr >> Shift) + SegCnt;
551 oP = &Slots[Fnum]; sP = &Slots[oP->
Own.
Next];
554 if (sP->Contents < lAddr) Left++;
555 else {sP->
Owner(Slots);
556 sP->
Hide(Slots, Slash, sP->Contents%HNum);
566 if (Dbg) std::cerr <<
"Cache: Trunc " <<Free <<
" slots; "
568 <<ioP->
Path() <<std::endl;
575 void XrdRmcReal::Upd(
char *Addr,
int wLen,
int wOff)
577 XrdRmcSlot *sP = &Slots[(Addr-Base)>>SegShft];
584 if (wLen + wOff > theLen)
596 <<
" slot " <<((Addr-Base)>>SegShft)
void * XrdRmcRealPRXeq(void *parg)
virtual const char * Path()=0
virtual int Read(char *buff, long long offs, int rlen)=0
static const int optRW
File is read/write (o/w read/only)
static const int optFIS
File is structured (e.g. root file)
static int setAPR(aprParms &Dest, aprParms &Src, int pSize)
XrdOucCacheIO * Attach(XrdOucCacheIO *ioP, int Options=0)
XrdRmcReal(int &rc, XrdRmc::Parms &Parms, XrdOucCacheIO::aprParms *aprP=0)
void File(XrdOucCacheIO *kV, int you)
void Owner(XrdRmcSlot *Base)
void unRef(XrdRmcSlot *Base)
static void Init(XrdRmcSlot *Base, int Num)
int Pull(XrdRmcSlot *Base)
void reRef(XrdRmcSlot *Base)
static int Find(XrdRmcSlot *Base, long long What, int n)
void Hide(XrdRmcSlot *Base, int *hTab, int hI)
static const int Debug
Produce some debug messages (levels 0, 1, 2, or 3)
static const int logStats
Display statistics upon detach.
static const int isServer
This is server application; not a user application.
static const int isStructured
static const int canPreRead
Enable pre-read operations (o/w ignored)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
Parameters for a newly created memory cache.
int MaxFiles
Maximum number of files (default 256 or 8K)
int PageSize
Size of each page in bytes (default 32KB)
long long CacheSize
Size of cache in bytes (default 100MB)
int Max2Cache
Largest read to cache (default PageSize)
short minPages
Minimum number of pages (default 256)
int Options
Options as defined below (default r/o cache)