XRootD
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"
36 #include "XrdSys/XrdSysPlatform.hh"
37 #include "XrdBuffXL.hh"
38 
39 /******************************************************************************/
40 /* L o c a l V a l u e s */
41 /******************************************************************************/
42 
43 namespace
44 {
45 static const int maxBuffSz = 1 << 30; //1 GB
46 static const int iniBuffSz = 1 << (XRD_BUSHIFT+XRD_BUCKETS-1);
47 static const int minBuffSz = 1 << (XRD_BUSHIFT+XRD_BUCKETS);
48 static const int minBShift = (XRD_BUSHIFT+XRD_BUCKETS);
49 static const int isBigBuff = 0x40000000;
50 }
51 
52 /******************************************************************************/
53 /* C o n s t r u c t o r */
54 /******************************************************************************/
55 
56 XrdBuffXL::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 
64 void 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 
155 int XrdBuffXL::Recalc(int sz)
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 
199 int 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
int bsize
Definition: XrdBuffer.hh:46
static int Log2(unsigned long long n)
Definition: XrdOucUtils.cc:818