MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DataBuffer2.hpp
1 /*
2  Copyright (c) 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_BUFFER2_HPP
19 #define DATA_BUFFER2_HPP
20 
27 template <Uint32 sz, typename Pool>
28 class DataBuffer2 {
29 public:
30  struct Segment {
31  Uint32 magic;
32  Uint32 nextPool;
33  Uint32 data[sz];
34  NdbOut& print(NdbOut& out){
35  out << "[DataBuffer<" << sz << ">::Segment this="
36  << this << dec << " nextPool= "
37  << nextPool << " ]";
38  return out;
39  }
40  };
41 public:
42  typedef Pool DataBufferPool;
43 
47  struct HeadPOD
48  {
49  Uint32 used; // Words used
50  Uint32 firstItem; // First segment (or RNIL)
51  Uint32 lastItem; // Last segment (or RNIL)
52 
53  void init() { used = 0; firstItem = lastItem = RNIL; }
54 
58  Uint32 getSize() const { return used;}
59 
63  static Uint32 getSegmentSize() { return sz;}
64  };
65 
66  struct Head : public HeadPOD
67  {
68  Head();
69 
70  Head& operator=(const HeadPOD& src) {
71  this->used = src.used;
72  this->firstItem = src.firstItem;
73  this->lastItem = src.lastItem;
74  return *this;
75  }
76  };
77 
80 
82  bool seize(Uint32 n);
83  void release();
84 
88  Uint32 getSize() const;
89 
93  bool isEmpty() const;
94 
98  static Uint32 getSegmentSize();
99 
100  void print(FILE*) const;
101 
102  /* ----------------------------------------------------------------------- */
103 
106  Ptr<Segment> curr; // Ptr to current segment
107  Uint32* data; // Pointer to current data (word)
108  Uint32 ind; // Word index within a segment
109  Uint32 pos; // Absolute word position within DataBuffer
110 
111  void print(FILE* out) {
112  fprintf(out, "[DataBufferIterator curr.i=%d, data=%p, ind=%d, pos=%d]\n",
113  curr.i, (void*) data, ind, pos);
114  };
115 
116  inline void assign(const ConstDataBufferIterator& src);
117  inline bool isNull() const { return curr.isNull();}
118  inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
119  };
121 
123  ConstPtr<Segment> curr;
124  const Uint32 * data;
125  Uint32 ind;
126  Uint32 pos;
127 
128  inline void assign(const DataBufferIterator& src);
129  inline bool isNull() const { return curr.isNull();}
130  inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
131  };
132 
138  bool first(DataBufferIterator &);
139  bool next(DataBufferIterator &);
140  bool next(DataBufferIterator &, Uint32 hops);
141  bool nextPool(DataBufferIterator &);
142 
146  bool position(DataBufferIterator& it, Uint32 pos);
147 
149  bool first(ConstDataBufferIterator &) const;
150  bool next(ConstDataBufferIterator &) const;
151  bool next(ConstDataBufferIterator &, Uint32 hops) const;
152  bool nextPool(ConstDataBufferIterator &) const;
153 
158  bool importable(const DataBufferIterator, Uint32 len);
159 
167  bool import(const DataBufferIterator &, const Uint32* src, Uint32 len);
168 
173  bool append(const Uint32* src, Uint32 len);
174 
175  static void createRecordInfo(Record_info & ri, Uint32 type_id);
176 protected:
177  Head head;
178  DataBufferPool & thePool;
179 
180 private:
185  bool import(Uint32 pos, const Uint32* src, Uint32 len);
186 };
187 
188 template<Uint32 sz, typename Pool>
189 class LocalDataBuffer2 : public DataBuffer2<sz, Pool> {
190 public:
192  typename DataBuffer2<sz, Pool>::HeadPOD & _src)
193  : DataBuffer2<sz, Pool>(thePool), src(_src)
194  {
195  this->head = src;
196  }
197 
198  ~LocalDataBuffer2(){
199  src = this->head;
200  }
201 private:
202  typename DataBuffer2<sz, Pool>::HeadPOD & src;
203 };
204 
205 template<Uint32 sz, typename Pool>
206 inline
208  this->init();
209 }
210 
211 template<Uint32 sz, typename Pool>
212 inline
214  return (it.pos + len < head.used);
215 }
216 
217 template<Uint32 sz, typename Pool>
218 inline
220 
221  // TODO: The current implementation is not the most effective one.
222  // A more effective implementation would start at the current
223  // position of the iterator.
224 
225  if(!first(it)){
226  return false;
227  }
228  return next(it, p);
229 }
230 
231 template<Uint32 sz, typename Pool>
232 inline
233 bool
235  const Uint32* src, Uint32 len)
236 {
237  Uint32 ind = (it.pos % sz);
238  Uint32 left = sz - ind;
239  Segment * p = it.curr.p;
240 
241  if (left)
242  {
243  memcpy(p->data+ind, src, 4 * left);
244  if (len <= left)
245  return true;
246 
247  src += left;
248  len -= left;
249  }
250 
251  while (len > sz)
252  {
253  p = static_cast<Segment*>(thePool.getPtr(p->nextPool));
254  memcpy(p->data, src, 4 * sz);
255  src += sz;
256  len -= sz;
257  }
258 
259  if (len)
260  {
261  p = static_cast<Segment*>(thePool.getPtr(p->nextPool));
262  memcpy(p->data, src, 4 * len);
263  }
264 
265  return true;
266 }
267 
268 template<Uint32 sz, typename Pool>
269 inline
270 bool
271 DataBuffer2<sz, Pool>::append(const Uint32* src, Uint32 len){
272  if(len == 0)
273  return true;
274 
275  Uint32 pos = head.used;
276  if(!seize(len)){
277  return false;
278  }
280 
281  if(position(it, pos) && import(it, src, len)){
282  return true;
283  }
284  abort();
285  return false;
286 }
287 
288 template<Uint32 sz, typename Pool>
289 inline
290 void DataBuffer2<sz, Pool>::print(FILE* out) const {
291  fprintf(out, "[DataBuffer used=%d words, segmentsize=%d words",
292  head.used, sz);
293 
294  if (head.firstItem == RNIL) {
295  fprintf(out, ": No segments seized.]\n");
296  return;
297  } else {
298  fprintf(out, "\n");
299  }
300 
301  Ptr<Segment> ptr;
302  ptr.i = head.firstItem;
303 
304  Uint32 acc = 0;
305  for(; ptr.i != RNIL; ){
306  ptr.p = (Segment*)thePool.getPtr(ptr.i);
307  const Uint32 * rest = ptr.p->data;
308  for(Uint32 i = 0; i<sz; i++){
309  fprintf(out, " H'%.8x", rest[i]);
310  if(acc++ == 6){
311  acc = 0;
312  fprintf(out, "\n");
313  }
314  }
315  ptr.i = ptr.p->nextPool;
316  }
317  fprintf(out, " ]\n");
318 }
319 
320 template<Uint32 sz, typename Pool>
321 inline
323 }
324 
325 template<Uint32 sz, typename Pool>
326 inline
327 bool
329  Uint32 rest; // Free space in last segment (currently)
330 
331  if(head.firstItem == RNIL)
332  {
333  rest = 0;
334  }
335  else
336  {
337  rest = (sz - (head.used % sz)) % sz;
338  }
339 
340  if (0)
341  ndbout_c("seize(%u) used: %u rest: %u firstItem: 0x%x",
342  n, head.used, rest, head.firstItem);
343 
344  if (rest >= n)
345  {
346  head.used += n;
347  return true;
348  }
349 
350  Uint32 used = head.used + n;
351  Segment first;
352  Ptr<Segment> currPtr;
353  currPtr.p = &first;
354  first.nextPool = RNIL;
355 
356  while (n >= sz)
357  {
358  Ptr<void> tmp;
359  if (thePool.seize(tmp))
360  {
361  currPtr.p->nextPool = tmp.i;
362  currPtr.i = tmp.i;
363  currPtr.p = static_cast<Segment*>(tmp.p);
364  }
365  else
366  {
367  goto error;
368  }
369  n -= sz;
370  }
371 
372  if(n > rest)
373  {
374  Ptr<void> tmp;
375  if (thePool.seize(tmp))
376  {
377  currPtr.p->nextPool = tmp.i;
378  currPtr.i = tmp.i;
379  currPtr.p = static_cast<Segment*>(tmp.p);
380  }
381  else
382  {
383  goto error;
384  }
385  }
386 
387  if (head.firstItem == RNIL)
388  {
389  head.firstItem = first.nextPool;
390  }
391  else
392  {
393  Segment* lastPtr = static_cast<Segment*>(thePool.getPtr(head.lastItem));
394  lastPtr->nextPool = first.nextPool;
395  }
396 
397  head.used = used;
398  head.lastItem = currPtr.i;
399  currPtr.p->nextPool = RNIL;
400  return true;
401 
402 error:
403  currPtr.i = first.nextPool;
404  while (currPtr.i != RNIL)
405  {
406  currPtr.p = static_cast<Segment*>(thePool.getPtr(currPtr.i));
407  Ptr<void> tmp;
408  tmp.i = currPtr.i;
409  tmp.p = currPtr.p;
410  currPtr.i = currPtr.p->nextPool;
411  thePool.release(tmp);
412  }
413  return false;
414 }
415 
416 template<Uint32 sz, typename Pool>
417 inline
418 void
420  Ptr<void> tmp;
421  tmp.i = head.firstItem;
422  while (tmp.i != RNIL)
423  {
424  tmp.p = thePool.getPtr(tmp.i);
425  Uint32 next = static_cast<Segment*>(tmp.p)->nextPool;
426  thePool.release(tmp);
427  tmp.i = next;
428  }
429 }
430 
431 template<Uint32 sz, typename Pool>
432 inline
433 Uint32
435  return sz;
436 }
437 
438 template<Uint32 sz, typename Pool>
439 inline
440 bool
443  tmp.assign(it);
444  bool ret = first(tmp);
445  it.assign(tmp);
446  return ret;
447 }
448 
449 template<Uint32 sz, typename Pool>
450 inline
451 bool
452 DataBuffer2<sz, Pool>::next(DataBufferIterator & it){
453  ConstDataBufferIterator tmp;
454  tmp.assign(it);
455  bool ret = next(tmp);
456  it.assign(tmp);
457  return ret;
458 }
459 
460 template<Uint32 sz, typename Pool>
461 inline
462 bool
463 DataBuffer2<sz, Pool>::next(DataBufferIterator & it, Uint32 hops){
464  ConstDataBufferIterator tmp;
465  tmp.assign(it);
466  bool ret = next(tmp, hops);
467  it.assign(tmp);
468  return ret;
469 }
470 
471 template<Uint32 sz, typename Pool>
472 inline
473 bool
475  it.curr.i = head.firstItem;
476  if(it.curr.i == RNIL){
477  it.setNull();
478  return false;
479  }
480  it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
481  it.data = &it.curr.p->data[0];
482  it.ind = 0;
483  it.pos = 0;
484  return true;
485 }
486 
487 template<Uint32 sz, typename Pool>
488 inline
489 bool
490 DataBuffer2<sz, Pool>::next(ConstDataBufferIterator & it) const {
491  it.ind ++;
492  it.data ++;
493  it.pos ++;
494  if(it.ind < sz && it.pos < head.used){
495  return true;
496  }
497 
498  if(it.pos < head.used){
499  it.curr.i = it.curr.p->nextPool;
500 #ifdef ARRAY_GUARD
501  if(it.curr.i == RNIL){
511  ErrorReporter::handleAssert("DataBuffer2<sz, Pool>::next", __FILE__, __LINE__);
512  }
513 #endif
514  it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
515  it.data = &it.curr.p->data[0];
516  it.ind = 0;
517  return true;
518  }
519  it.setNull();
520  return false;
521 }
522 
523 template<Uint32 sz, typename Pool>
524 inline
525 bool
526 DataBuffer2<sz, Pool>::next(ConstDataBufferIterator & it, Uint32 hops) const {
527 #if 0
528  for (Uint32 i=0; i<hops; i++) {
529  if (!this->next(it))
530  return false;
531  }
532  return true;
533 #else
534  if(it.pos + hops < head.used){
535  while(hops >= sz){
536  it.curr.i = it.curr.p->nextPool;
537  it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
538  hops -= sz;
539  it.pos += sz;
540  }
541 
542  it.ind += hops;
543  it.pos += hops;
544  if(it.ind < sz){
545  it.data = &it.curr.p->data[it.ind];
546  return true;
547  }
548 
549  it.curr.i = it.curr.p->nextPool;
550  it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
551  it.ind -= sz;
552  it.data = &it.curr.p->data[it.ind];
553  return true;
554  }
555  it.setNull();
556  return false;
557 #endif
558 }
559 
560 template<Uint32 sz, typename Pool>
561 inline
562 Uint32
564  return head.used;
565 }
566 
567 template<Uint32 sz, typename Pool>
568 inline
569 bool
571  return (head.used == 0);
572 }
573 
574 template<Uint32 sz, typename Pool>
575 inline
576 void
578 {
579  Segment tmp;
580  const char * off_base = (char*)&tmp;
581  const char * off_next = (char*)&tmp.nextPool;
582  const char * off_magic = (char*)&tmp.magic;
583 
584  ri.m_size = sizeof(tmp);
585  ri.m_offset_next_pool = Uint32(off_next - off_base);
586  ri.m_offset_magic = Uint32(off_magic - off_base);
587  ri.m_type_id = type_id;
588 }
589 
590 template<Uint32 sz, typename Pool>
591 inline
592 void
593 DataBuffer2<sz, Pool>::DataBufferIterator::assign(const ConstDataBufferIterator & src)
594 {
595  this->curr.i = src.curr.i;
596  this->curr.p = const_cast<Segment*>(src.curr.p);
597  this->data = const_cast<Uint32*>(src.data);
598  this->ind = src.ind;
599  this->pos = src.pos;
600 }
601 
602 template<Uint32 sz, typename Pool>
603 inline
604 void
605 DataBuffer2<sz, Pool>::ConstDataBufferIterator::assign(const DataBufferIterator & src)
606 {
607  this->curr.i = src.curr.i;
608  this->curr.p = src.curr.p;
609  this->data = src.data;
610  this->ind = src.ind;
611  this->pos = src.pos;
612 }
613 
614 #endif
615