XRootD
XrdOucBuffer.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O u c B u f f e r . c c */
4 /* */
5 /* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #ifndef WIN32
32 #include <unistd.h>
33 #endif
34 #include <sys/types.h>
35 #include <cstdlib>
36 
37 #include "XrdOuc/XrdOucBuffer.hh"
38 #include "XrdSys/XrdSysPlatform.hh"
39 
40 /******************************************************************************/
41 /* S t a t i c M e m b e r s */
42 /******************************************************************************/
43 
44 int XrdOucBuffPool::alignit = sysconf(_SC_PAGESIZE);
45 
46 /******************************************************************************/
47 /* X r d O u c B u f f P o o l M e t h o d s */
48 /******************************************************************************/
49 /******************************************************************************/
50 /* C o n s t r u c t o r */
51 /******************************************************************************/
52 
53 XrdOucBuffPool::XrdOucBuffPool(int minsz, int maxsz,
54  int minh, int maxh, int rate)
55 {
56  int keep, pct, i, n = 0;
57 
58 // Adjust the minsz
59 //
60  while(minsz > 1024*(1<<n)) n++;
61  if (n > 14) n = 14;
62  else if (n && minsz < 1024*(1<<n)) n--;
63  incBsz = 1024*(1<<n);
64  shfBsz = 10 + n;
65  rndBsz = incBsz - 1;
66  if (maxh < 0) maxh = 0;
67  if (minh < 0) minh = 0;
68  if (maxh < minh) maxh = minh;
69  if (rate < 0) rate = 0;
70 
71 // Round up the maxsz and make it a multiple of 4k
72 //
73  if (!(slots = maxsz / incBsz)) slots = 1;
74  else if (maxsz % incBsz) slots++;
75  maxBsz = slots << shfBsz;
76 
77 // Allocate a slot vector for this
78 //
79  bSlot = new BuffSlot[(unsigned int)slots];
80 
81 // Complete initializing the slot vector
82 //
83  n = incBsz;
84  for (i = 0; i < slots; i++)
85  {bSlot[i].size = n; n += incBsz;
86  pct = (slots - i + 1)*100/slots;
87  if (pct >= 100) keep = maxh;
88  else {keep = ((maxh * pct) + 55)/100 - i*rate;
89  if (keep > maxh) keep = maxh;
90  else if (keep < minh) keep = minh;
91  }
92  bSlot[i].maxbuff = keep;
93  }
94 }
95 
96 /******************************************************************************/
97 /* A l l o c */
98 /******************************************************************************/
99 
101 {
102  XrdOucBuffPool::BuffSlot *sP;
103  XrdOucBuffer *bP;
104  int snum;
105 
106 // Compute buffer slot
107 //
108  snum = (bsz <= incBsz ? 0 : (bsz + rndBsz) >> shfBsz);
109  if (snum >= slots) return 0;
110  sP = &bSlot[snum];
111 
112 // Lock the data area
113 //
114  sP->SlotMutex.Lock();
115 
116 // Either return a new buffer or an old one
117 //
118  if ((bP = sP->buffFree))
119  {sP->buffFree = bP->buffNext;
120  bP->buffPool = this;
121  sP->numbuff--;
122  } else {
123  if ((bP = new XrdOucBuffer(this, snum)))
124  {int mema;
125  if (sP->size >= alignit) mema = alignit;
126  else if (sP->size > 2048) mema = 4096;
127  else if (sP->size > 1024) mema = 2048;
128  else mema = 1024;
129  if (posix_memalign((void **)&(bP->data), mema, sP->size))
130  {delete bP; bP = 0;}
131  }
132  }
133 
134 // Unlock the data area
135 //
136  sP->SlotMutex.UnLock();
137 
138 // Return the buffer
139 //
140  return bP;
141 }
142 
143 /******************************************************************************/
144 /* X r d O u c B u f f P o o l : : B u f f S l o t M e t h o d s */
145 /******************************************************************************/
146 /******************************************************************************/
147 /* D e s t r u c t o r */
148 /******************************************************************************/
149 
150 XrdOucBuffPool::BuffSlot::~BuffSlot()
151 {
152  XrdOucBuffer *bP;
153 
154  while((bP = buffFree)) {buffFree = buffFree->buffNext; delete bP;}
155 }
156 
157 /******************************************************************************/
158 /* R e c y c l e */
159 /******************************************************************************/
160 
161 void XrdOucBuffPool::BuffSlot::Recycle(XrdOucBuffer *bP)
162 {
163 
164 // Check if we have enough objects, if so, delete ourselves and return
165 //
166  if (numbuff >= maxbuff) {delete bP; return;}
167  bP->dlen = 0;
168  bP->doff = 0;
169 
170 // Add the buffer to the recycle list
171 //
172  SlotMutex.Lock();
173  bP->buffNext = buffFree;
174  buffFree = bP;
175  numbuff++;
176  SlotMutex.UnLock();
177  return;
178 }
179 
180 /******************************************************************************/
181 /* X r d O u c B u f f e r M e t h o d s */
182 /******************************************************************************/
183 /******************************************************************************/
184 /* P u b l i c C o n s t r u c t o r */
185 /******************************************************************************/
186 
187 XrdOucBuffer::XrdOucBuffer(char *buff, int blen)
188 {
189  static XrdOucBuffPool nullPool(0, 0, 0, 0, 0);
190 
191 // Initialize the one time buffer
192 //
193  data = buff;
194  dlen = blen;
195  doff = 0;
196  size = blen;
197  slot = 0;
198  buffPool = &nullPool;
199 };
200 
201 /******************************************************************************/
202 /* C l o n e */
203 /******************************************************************************/
204 
206 {
207  XrdOucBuffer *newbP;
208  int newsz;
209 
210 // Compute the size of the new buffer
211 //
212  newsz = (trim ? doff+dlen : size);
213 
214 // Allocate a new buffer
215 //
216  if (!(newbP = buffPool->Alloc(newsz))) return 0;
217 
218 // Copy the data and the information
219 //
220  newbP->dlen = dlen;
221  newbP->doff = doff;
222  memcpy(newbP->data, data, dlen+doff);
223  return newbP;
224 }
225 
226 /******************************************************************************/
227 /* H i g h j a c k */
228 /******************************************************************************/
229 
231 {
232  XrdOucBuffer tempBuff, *newbP;
233 
234 // Adjust the size to revert highjacked buffer
235 //
236  if (xsz <= 0) xsz = size;
237 
238 // Allocate a new buffer
239 //
240  if (!(newbP = buffPool->Alloc(xsz))) return 0;
241 
242 // Swap information
243 //
244  tempBuff = *this;
245  *this = *newbP;
246  *newbP = tempBuff;
247  tempBuff.data = 0;
248  return newbP;
249 }
250 
251 /******************************************************************************/
252 /* R e s i z e */
253 /******************************************************************************/
254 
255 bool XrdOucBuffer::Resize(int newsz)
256 {
257 
258 // If the new size differs from the old size, reallocate by simply highjacking
259 // the buffer and releasing the newly acquired one.
260 //
261  if (newsz != size)
262  {XrdOucBuffer *newbP;
263  if (!(newbP = Highjack(newsz))) return false;
264  newbP->Recycle();
265  }
266  return true;
267 }
void trim(std::string &str)
Definition: XrdHttpReq.cc:76
XrdOucBuffer * Alloc(int sz)
XrdOucBuffPool(int minsz=4096, int maxsz=65536, int minh=1, int maxh=16, int rate=1)
Definition: XrdOucBuffer.cc:53
friend class XrdOucBuffer
Definition: XrdOucBuffer.hh:56
bool Resize(int newsz)
XrdOucBuffer(char *buff, int blen)
XrdOucBuffer * Clone(bool trim=true)
void Recycle()
Recycle the buffer. The buffer may be reused in the future.
XrdOucBuffer * Highjack(int bPsz=0)