XRootD
Loading...
Searching...
No Matches
XrdBuffXL.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d B u f f X L . c c */
4/* */
5/* (c) 2015 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 <unistd.h>
31#include <cstdio>
32#include <cstdlib>
33#include <sys/types.h>
34
35#include "XrdOuc/XrdOucUtils.hh"
37#include "XrdBuffXL.hh"
38
39/******************************************************************************/
40/* L o c a l V a l u e s */
41/******************************************************************************/
42
43namespace
44{
45static const int maxBuffSz = 1 << 30; //1 GB
46static const int iniBuffSz = 1 << (XRD_BUSHIFT+XRD_BUCKETS-1);
47static const int minBuffSz = 1 << (XRD_BUSHIFT+XRD_BUCKETS);
48static const int minBShift = (XRD_BUSHIFT+XRD_BUCKETS);
49static const int isBigBuff = 0x40000000;
50}
51
52/******************************************************************************/
53/* C o n s t r u c t o r */
54/******************************************************************************/
55
56XrdBuffXL::XrdBuffXL() : bucket(0), totalo(0), pagsz(getpagesize()), slots(0),
57 maxsz(1<<(XRD_BUSHIFT+XRD_BUCKETS-1)), totreq(0)
58{ }
59
60/******************************************************************************/
61/* I n i t */
62/******************************************************************************/
63
64void XrdBuffXL::Init(int maxMSZ)
65{
66 unsigned int lg2;
67 int chunksz;
68
69// If this is a duplicate call, delete the previous setup
70//
71 if (bucket) {delete [] bucket; bucket = 0;}
72
73// Check if this is too small for us
74//
75 if (maxMSZ <= iniBuffSz) {maxsz = iniBuffSz; return;}
76
77// Check if this is too large for us (1GB limit) and adjust
78//
79 if (maxMSZ > maxBuffSz) maxMSZ = maxBuffSz;
80
81// Calculate how many buckets we need to have (note we trim this down
82//
83 chunksz = maxMSZ >> minBShift;
84 lg2 = XrdOucUtils::Log2(chunksz);
85 chunksz = 1<<(lg2+minBShift);
86 if (chunksz < maxMSZ) {lg2++; maxsz = chunksz << 1;}
87 else maxsz = chunksz;
88
89// Allocate a bucket array
90//
91 bucket = new BuckVec[lg2+1];
92 slots = lg2+1;
93}
94
95/******************************************************************************/
96/* O b t a i n */
97/******************************************************************************/
98
100{
101 XrdBuffer *bp;
102 char *memp;
103 int mk, buffSz, bindex = 0;
104
105// Make sure the request is within our limits
106//
107 if (sz <= 0 || sz > maxsz) return 0;
108
109// Calculate bucket index. This is log2(shifted size) rounded up if need be.
110// If the shift results in zero we know the request fits in the slot 0 buffer.
111//
112 mk = sz >> minBShift;
113 if (!mk) buffSz = minBuffSz;
114 else {bindex = XrdOucUtils::Log2(mk);
115 buffSz = (bindex ? minBuffSz << bindex : minBuffSz);
116 if (buffSz < sz) {bindex++; buffSz = buffSz << 1;}
117 }
118 if (bindex >= slots) return 0; // Should never happen!
119
120// Obtain a lock on the bucket array and try to give away an existing buffer
121//
122 slotXL.Lock();
123 totreq++;
124 bucket[bindex].numreq++;
125 if ((bp = bucket[bindex].bnext))
126 {bucket[bindex].bnext = bp->next; bucket[bindex].numbuf--;}
127 slotXL.UnLock();
128
129// Check if we really allocated a buffer
130//
131 if (bp) return bp;
132
133// Allocate a chunk of aligned memory
134//
135 if (posix_memalign((void **)&memp, pagsz, buffSz)) return 0;
136
137// Wrap the memory with a buffer object
138//
139 if (!(bp = new XrdBuffer(memp, buffSz, bindex|isBigBuff)))
140 {free(memp); return 0;}
141
142// Update statistics
143//
144 slotXL.Lock(); totalo += buffSz; totbuf++; slotXL.UnLock();
145
146// Return the buffer
147//
148 return bp;
149}
150
151/******************************************************************************/
152/* R e c a l c */
153/******************************************************************************/
154
156{
157 int buffSz, mk, bindex = 0;
158
159// Make sure the request is within our limits
160//
161 if (sz <= 0 || sz > maxsz) return 0;
162
163// Calculate bucket size corresponding to the desired size
164//
165 mk = sz >> minBShift;
166 if (!mk) buffSz = minBuffSz;
167 else {bindex = XrdOucUtils::Log2(mk);
168 buffSz = (bindex ? minBuffSz << bindex : minBuffSz);
169 if (buffSz < sz) {bindex++; buffSz = buffSz << 1;}
170 }
171 if (bindex >= slots) return 0; // Should never happen!
172
173// All done, return the actual size we would have allocated
174//
175 return buffSz;
176}
177
178/******************************************************************************/
179/* R e l e a s e */
180/******************************************************************************/
181
183{
184 int bindex = bp->bindex & ~isBigBuff;
185
186// Obtain a lock on the bucket array and reclaim the buffer
187//
188 slotXL.Lock();
189 bp->next = bucket[bindex].bnext;
190 bucket[bindex].bnext = bp;
191 bucket[bindex].numbuf++;
192 slotXL.UnLock();
193}
194
195/******************************************************************************/
196/* S t a t s */
197/******************************************************************************/
198
199int XrdBuffXL::Stats(char *buff, int blen, int do_sync)
200{
201 static char statfmt[] = "<xlreqs>%d</xlreqs>"
202 "<xlmem>%lld</xlmem><xlbuffs>%d</xlbuffs>";
203 int nlen;
204
205// If only size wanted, return it
206//
207 if (!buff) return sizeof(statfmt) + 16*3;
208
209// Return formatted stats
210//
211 if (do_sync) slotXL.Lock();
212 nlen = snprintf(buff, blen, statfmt, totreq, totalo, totbuf);
213 if (do_sync) slotXL.UnLock();
214 return nlen;
215}
216
217/******************************************************************************/
218/* T r i m */
219/******************************************************************************/
220
222{
223 XrdBuffer *bP;
224 int n, m;
225
226// Obtain the lock
227//
228 slotXL.Lock();
229
230// Run through all our slots looking for buffers to release
231//
232 for (int i = 0; i < slots; i++)
233 {if (bucket[i].numbuf > 1 && bucket[i].numbuf > bucket[i].numreq)
234 {n = bucket[i].numbuf - bucket[i].numreq;
235 m = bucket[i].numbuf/2;
236 if (m < n) n = m;
237 while(n-- && (bP = bucket[i].bnext))
238 {bucket[i].bnext = bP->next;
239 bucket[i].numbuf--;
240 totalo -= bP->bsize; totbuf--;
241 delete bP;
242 }
243 }
244 bucket[i].numreq = 0;
245 }
246
247// Release the lock
248//
249 slotXL.UnLock();
250}
#define XRD_BUSHIFT
Definition XrdBuffer.hh:67
#define XRD_BUCKETS
Definition XrdBuffer.hh:66
void Release(XrdBuffer *bp)
Definition XrdBuffXL.cc:182
void Trim()
Definition XrdBuffXL.cc:221
int Recalc(int bsz)
Definition XrdBuffXL.cc:155
void Init(int maxMSZ)
Definition XrdBuffXL.cc:64
int Stats(char *buff, int blen, int do_sync=0)
Definition XrdBuffXL.cc:199
XrdBuffer * Obtain(int bsz)
Definition XrdBuffXL.cc:99
static int Log2(unsigned long long n)