MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DataBuffer.hpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #ifndef DATA_BUFFER_HPP
19 #define DATA_BUFFER_HPP
20 
21 #include "ArrayPool.hpp"
22 
29 template <Uint32 sz>
30 class DataBuffer {
31 public:
32  struct Segment {
33  Uint32 nextPool;
34  Uint32 data[sz];
35  NdbOut& print(NdbOut& out){
36  out << "[DataBuffer<" << sz << ">::Segment this="
37  << this << dec << " nextPool= "
38  << nextPool << " ]";
39  return out;
40  }
41  };
42 public:
44 
48  struct Head {
49  Head() ;
50 
51  Uint32 used; // Words used
52  Uint32 firstItem; // First segment (or RNIL)
53  Uint32 lastItem; // Last segment (or RNIL)
54 
58  Uint32 getSize() const { return used;}
59 
63  static Uint32 getSegmentSize() { return sz;}
64  };
65 
67  DataBuffer(DataBufferPool &);
68 
70  bool seize(Uint32 n);
71  void release();
72 
76  Uint32 getSize() const;
77 
81  bool isEmpty() const;
82 
86  static Uint32 getSegmentSize();
87 
88  void print(FILE*) const;
89 
90  /* ----------------------------------------------------------------------- */
91 
93  Ptr<Segment> curr; // Ptr to current segment
94  Uint32* data; // Pointer to current data (word)
95  Uint32 ind; // Word index within a segment
96  Uint32 pos; // Absolute word position within DataBuffer
97 
98  void print(FILE* out) {
99  fprintf(out, "[DataBufferIterator curr.i=%d, data=%p, ind=%d, pos=%d]\n",
100  curr.i, (void*) data, ind, pos);
101  };
102 
103  inline bool isNull() const { return curr.isNull();}
104  inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
105  };
107 
109  ConstPtr<Segment> curr;
110  const Uint32 * data;
111  Uint32 ind;
112  Uint32 pos;
113 
114  inline bool isNull() const { return curr.isNull();}
115  inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
116  };
117 
123  bool first(DataBufferIterator &);
124  bool next(DataBufferIterator &);
125  bool next(DataBufferIterator &, Uint32 hops);
126  bool nextPool(DataBufferIterator &);
127 
131  bool position(DataBufferIterator& it, Uint32 pos);
132 
134  bool first(ConstDataBufferIterator &) const;
135  bool next(ConstDataBufferIterator &) const;
136  bool next(ConstDataBufferIterator &, Uint32 hops) const;
137  bool nextPool(ConstDataBufferIterator &) const;
138 
143  bool importable(const DataBufferIterator, Uint32 len);
144 
152  bool import(const DataBufferIterator &, const Uint32* src, Uint32 len);
153 
158  bool append(const Uint32* src, Uint32 len);
159 
160 protected:
161  Head head;
162  DataBufferPool & thePool;
163 
164 private:
169  bool import(Uint32 pos, const Uint32* src, Uint32 len);
170 };
171 
172 template<Uint32 sz>
173 class LocalDataBuffer : public DataBuffer<sz> {
174 public:
176  typename DataBuffer<sz>::Head & _src)
177  : DataBuffer<sz>(thePool), src(_src)
178  {
179  this->head = src;
180  }
181 
182  ~LocalDataBuffer(){
183  src = this->head;
184  }
185 private:
186  typename DataBuffer<sz>::Head & src;
187 };
188 
189 template<Uint32 sz>
190 inline
192  used = 0;
193  firstItem = RNIL;
194  lastItem = RNIL;
195 }
196 
197 template<Uint32 sz>
198 inline
200  return (it.pos + len < head.used);
201 }
202 
203 template<Uint32 sz>
204 inline
206 
207  // TODO: The current implementation is not the most effective one.
208  // A more effective implementation would start at the current
209  // position of the iterator.
210 
211  if(!first(it)){
212  return false;
213  }
214  return next(it, p);
215 }
216 
217 template<Uint32 sz>
218 inline
219 bool
221  const Uint32* src, Uint32 len){
222 
223 #if 0
225  position(it, _it.pos);
226 
227  for(; len > 0; len--){
228  Uint32 s = * src;
229  * it.data = s;
230  next(it);
231  src++;
232  }
233  return true;
234 #else
235  Uint32 ind = (it.pos % sz);
236  Uint32 left = sz - ind;
237  Segment * p = it.curr.p;
238 
239  while(len > left){
240  memcpy(&p->data[ind], src, 4 * left);
241  src += left;
242  len -= left;
243  ind = 0;
244  left = sz;
245  p = thePool.getPtr(p->nextPool);
246  }
247 
248  memcpy(&p->data[ind], src, 4 * len);
249  return true;
250 #endif
251 }
252 
253 template<Uint32 sz>
254 inline
255 bool
256 DataBuffer<sz>::append(const Uint32* src, Uint32 len){
257  if(len == 0)
258  return true;
259 
260  Uint32 pos = head.used;
261  if(!seize(len)){
262  return false;
263  }
265 
266  bool b0, b1;
267  if ((b0 = position(it, pos)) && (b1 = import(it, src, len)))
268  {
269  return true;
270  }
271 
272  ndbout_c("%u %u", b0, b1);
273  abort();
274  return false;
275 }
276 
277 template<Uint32 sz>
278 inline
279 void DataBuffer<sz>::print(FILE* out) const {
280  fprintf(out, "[DataBuffer used=%d words, segmentsize=%d words",
281  head.used, sz);
282 
283  if (head.firstItem == RNIL) {
284  fprintf(out, ": No segments seized.]\n");
285  return;
286  } else {
287  fprintf(out, "\n");
288  }
289 
290  Ptr<Segment> ptr;
291  ptr.i = head.firstItem;
292 
293  Uint32 acc = 0;
294  for(; ptr.i != RNIL; ){
295  thePool.getPtr(ptr);
296  const Uint32 * rest = ptr.p->data;
297  for(Uint32 i = 0; i<sz; i++){
298  fprintf(out, " H'%.8x", rest[i]);
299  if(acc++ == 6){
300  acc = 0;
301  fprintf(out, "\n");
302  }
303  }
304  ptr.i = ptr.p->nextPool;
305  }
306  fprintf(out, " ]\n");
307 }
308 
309 template<Uint32 sz>
310 inline
312 }
313 
314 template<Uint32 sz>
315 inline
316 bool
318 {
319  Uint32 req = n;
320  Uint32 used = head.used;
321  Uint32 last = used % sz; // (almost) used in last segment
322  Uint32 rest = last ? sz - last : 0; // Free in last segment
323 
324  if (rest >= n)
325  {
329  head.used = used + n;
330  return true;
331  }
332 
333  n -= rest;
334 
338  Uint32 free = thePool.getNoOfFree() * sz;
339  if (n > free)
340  {
341  return false;
342  }
343 
344  Ptr<Segment> firstPtr;
345  thePool.seize(firstPtr);
346  Ptr<Segment> lastPtr = firstPtr;
347 
348  while (n > sz)
349  {
350  Ptr<Segment> tmp;
351  thePool.seize(tmp);
352  lastPtr.p->nextPool = tmp.i;
353  lastPtr = tmp;
354  n -= sz;
355  }
356  lastPtr.p->nextPool = RNIL;
357 
358  head.used = used + req;
359  if (head.firstItem == RNIL)
360  {
361  head.firstItem = firstPtr.i;
362  assert(head.lastItem == RNIL);
363  }
364  else
365  {
366  Segment* tail = thePool.getPtr(head.lastItem);
367  assert(tail->nextPool == RNIL);
368  tail->nextPool = firstPtr.i;
369  }
370  head.lastItem = lastPtr.i;
371 
372 #if 0
373  {
374  ndbout_c("Before validate - %d", head.used);
375  if(head.used == 0){
376  assert(head.firstItem == RNIL);
377  assert(head.lastItem == RNIL);
378  } else {
379  Ptr<Segment> tmp;
380  tmp.i = head.firstItem;
381  for(Uint32 i = head.used; i > sz; i -= sz){
382  ndbout << tmp.i << " ";
383  tmp.p = thePool.getPtr(tmp.i);
384  tmp.i = tmp.p->nextPool;
385  }
386  ndbout_c("%d", tmp.i);
387  assert(head.lastItem == tmp.i);
388  }
389  ndbout_c("After validate");
390  }
391 #endif
392  return true;
393 }
394 
395 template<Uint32 sz>
396 inline
397 void
399  Uint32 used = head.used + sz - 1;
400  if(head.firstItem != RNIL){
401  thePool.releaseList(used / sz, head.firstItem, head.lastItem);
402  head.used = 0;
403  head.firstItem = RNIL;
404  head.lastItem = RNIL;
405  }
406 }
407 
408 template<Uint32 sz>
409 inline
410 Uint32
412  return sz;
413 }
414 
415 template<Uint32 sz>
416 inline
417 bool
419  it.curr.i = head.firstItem;
420  if(it.curr.i == RNIL){
421  it.setNull();
422  return false;
423  }
424  thePool.getPtr(it.curr);
425  it.data = &it.curr.p->data[0];
426  it.ind = 0;
427  it.pos = 0;
428  return true;
429 }
430 
431 template<Uint32 sz>
432 inline
433 bool
434 DataBuffer<sz>::next(DataBufferIterator & it){
435  it.ind ++;
436  it.data ++;
437  it.pos ++;
438  if(it.ind < sz && it.pos < head.used){
439  return true;
440  }
441 
442  if(it.pos < head.used){
443  it.curr.i = it.curr.p->nextPool;
444 #ifdef ARRAY_GUARD
445  if(it.curr.i == RNIL){
455  ErrorReporter::handleAssert("DataBuffer<sz>::next", __FILE__, __LINE__);
456  }
457 #endif
458  thePool.getPtr(it.curr);
459  it.data = &it.curr.p->data[0];
460  it.ind = 0;
461  return true;
462  }
463  it.setNull();
464  return false;
465 }
466 
467 template<Uint32 sz>
468 inline
469 bool
470 DataBuffer<sz>::next(DataBufferIterator & it, Uint32 hops){
471 #if 0
472  for (Uint32 i=0; i<hops; i++) {
473  if (!this->next(it))
474  return false;
475  }
476  return true;
477 #else
478  if(it.pos + hops < head.used){
479  while(hops >= sz){
480  it.curr.i = it.curr.p->nextPool;
481  thePool.getPtr(it.curr);
482  hops -= sz;
483  it.pos += sz;
484  }
485 
486  it.ind += hops;
487  it.pos += hops;
488  if(it.ind < sz){
489  it.data = &it.curr.p->data[it.ind];
490  return true;
491  }
492 
493  it.curr.i = it.curr.p->nextPool;
494  thePool.getPtr(it.curr);
495  it.ind -= sz;
496  it.data = &it.curr.p->data[it.ind];
497  return true;
498  }
499  it.setNull();
500  return false;
501 #endif
502 }
503 
504 template<Uint32 sz>
505 inline
506 bool
508  it.curr.i = head.firstItem;
509  if(it.curr.i == RNIL){
510  it.setNull();
511  return false;
512  }
513  thePool.getPtr(it.curr);
514  it.data = &it.curr.p->data[0];
515  it.ind = 0;
516  it.pos = 0;
517  return true;
518 }
519 
520 template<Uint32 sz>
521 inline
522 bool
523 DataBuffer<sz>::next(ConstDataBufferIterator & it) const {
524  it.ind ++;
525  it.data ++;
526  it.pos ++;
527  if(it.ind < sz && it.pos < head.used){
528  return true;
529  }
530 
531  if(it.pos < head.used){
532  it.curr.i = it.curr.p->nextPool;
533 #ifdef ARRAY_GUARD
534  if(it.curr.i == RNIL){
544  ErrorReporter::handleAssert("DataBuffer<sz>::next", __FILE__, __LINE__);
545  }
546 #endif
547  thePool.getPtr(it.curr);
548  it.data = &it.curr.p->data[0];
549  it.ind = 0;
550  return true;
551  }
552  it.setNull();
553  return false;
554 }
555 
556 template<Uint32 sz>
557 inline
558 bool
559 DataBuffer<sz>::next(ConstDataBufferIterator & it, Uint32 hops) const {
560 #if 0
561  for (Uint32 i=0; i<hops; i++) {
562  if (!this->next(it))
563  return false;
564  }
565  return true;
566 #else
567  if(it.pos + hops < head.used){
568  while(hops >= sz){
569  it.curr.i = it.curr.p->nextPool;
570  thePool.getPtr(it.curr);
571  hops -= sz;
572  it.pos += sz;
573  }
574 
575  it.ind += hops;
576  it.pos += hops;
577  if(it.ind < sz){
578  it.data = &it.curr.p->data[it.ind];
579  return true;
580  }
581 
582  it.curr.i = it.curr.p->nextPool;
583  thePool.getPtr(it.curr);
584  it.ind -= sz;
585  it.data = &it.curr.p->data[it.ind];
586  return true;
587  }
588  it.setNull();
589  return false;
590 #endif
591 }
592 
593 template<Uint32 sz>
594 inline
595 Uint32
597  return head.used;
598 }
599 
600 template<Uint32 sz>
601 inline
602 bool
604  return (head.used == 0);
605 }
606 
607 #endif
608