DataBuffer.hpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:11k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #ifndef DATA_BUFFER_HPP
  14. #define DATA_BUFFER_HPP
  15. #include "ArrayPool.hpp"
  16. /**
  17.  * @class  DataBuffer
  18.  * @brief  Buffer of data words
  19.  * 
  20.  * @note   The buffer is divided into segments (of size sz)
  21.  */
  22. template <Uint32 sz>
  23. class DataBuffer {
  24. public:
  25.   struct Segment {
  26.     Uint32 nextPool;
  27.     Uint32 data[sz];
  28.     NdbOut& print(NdbOut& out){
  29.       out << "[DataBuffer<" << sz << ">::Segment this=" 
  30.   << this << dec << " nextPool= "
  31.   << nextPool << " ]";
  32.       return out;
  33.     }
  34.   };
  35. public:
  36.   typedef ArrayPool<Segment> DataBufferPool;
  37.   /**
  38.    * Head/anchor for data buffer
  39.    */
  40.   struct Head {
  41.     Head() ;
  42.     Uint32 used;       // Words used
  43.     Uint32 firstItem;  // First segment (or RNIL)
  44.     Uint32 lastItem;   // Last segment (or RNIL)
  45.     /** 
  46.      * Get size of databuffer, in words
  47.      */
  48.     Uint32 getSize() const { return used;}
  49.     
  50.     /** 
  51.      * Get segment size in words (template argument) 
  52.      */
  53.     static Uint32 getSegmentSize() { return sz;}
  54.   };
  55.   /** Constructor */
  56.   DataBuffer(DataBufferPool &);
  57.   /** Seize <b>n</b> words, Release */
  58.   bool seize(Uint32 n);
  59.   void release();
  60.   /** 
  61.    * Get size of databuffer, in words
  62.    */
  63.   Uint32 getSize() const;
  64.   
  65.   /** 
  66.    * Check if buffer is empty
  67.    */
  68.   bool isEmpty() const;
  69.   
  70.   /**
  71.    * Get segment size in words (template argument) 
  72.    */
  73.   static Uint32 getSegmentSize();
  74.   
  75.   void print(FILE*) const;
  76.   /* ----------------------------------------------------------------------- */
  77.   struct DataBufferIterator {
  78.     Ptr<Segment>       curr;  // Ptr to current segment
  79.     Uint32*            data;  // Pointer to current data (word)
  80.     Uint32             ind;   // Word index within a segment
  81.     Uint32             pos;   // Absolute word position within DataBuffer
  82.     void print(FILE* out) {
  83.       fprintf(out, "[DataBufferIterator curr.i=%d, data=%p, ind=%d, pos=%d]n",
  84.       curr.i, (void*) data, ind, pos);
  85.     };
  86.     inline bool isNull() const { return curr.isNull();}
  87.     inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
  88.   };
  89.   
  90.   struct ConstDataBufferIterator {
  91.     ConstPtr<Segment>  curr;
  92.     const Uint32 *     data;
  93.     Uint32             ind;
  94.     Uint32             pos;
  95.     inline bool isNull() const { return curr.isNull();}
  96.     inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
  97.   };
  98.   /** 
  99.    * Iterator 
  100.    * @parameter hops  Number of words to jump forward
  101.    * @note DataBuffer::next returns false if applied to last word.
  102.    */
  103.   bool first(DataBufferIterator &);
  104.   bool next(DataBufferIterator &);
  105.   bool next(DataBufferIterator &, Uint32 hops);
  106.   bool nextPool(DataBufferIterator &);
  107.   /**
  108.    * Set iterator to position
  109.    */
  110.   bool position(DataBufferIterator& it, Uint32 pos);
  111.   /** Iterator */
  112.   bool first(ConstDataBufferIterator &) const;
  113.   bool next(ConstDataBufferIterator &) const;
  114.   bool next(ConstDataBufferIterator &, Uint32 hops) const;
  115.   bool nextPool(ConstDataBufferIterator &) const;
  116.   /** 
  117.    * Returns true if it is possible to store <em>len</em> 
  118.    * no of words at position given in iterator.
  119.    */
  120.   bool importable(const DataBufferIterator, Uint32 len);
  121.   /**
  122.    * Stores <em>len</em> no of words starting at location <em>src</em> in
  123.    * databuffer at position given in iterator.
  124.    * 
  125.    * @return true if success, false otherwise.
  126.    * @note Iterator is not advanced.
  127.    */
  128.   bool import(const DataBufferIterator &, const Uint32* src, Uint32 len);
  129.   /**
  130.    * Increases size with appends <em>len</em> words
  131.    * @return true if success, false otherwise.
  132.    */
  133.   bool append(const Uint32* src, Uint32 len);
  134. protected:
  135.   Head head;
  136.   DataBufferPool &  thePool;
  137. private:
  138.   /**
  139.    * This is NOT a public method, since the intension is that the import
  140.    * method using iterators will be more effective in the future 
  141.    */
  142.   bool import(Uint32 pos, const Uint32* src, Uint32 len);
  143. };
  144. template<Uint32 sz>
  145. class LocalDataBuffer : public DataBuffer<sz> {
  146. public:
  147.   LocalDataBuffer(typename DataBuffer<sz>::DataBufferPool & thePool, 
  148.   typename DataBuffer<sz>::Head & _src)
  149.     : DataBuffer<sz>(thePool), src(_src)
  150.   {
  151.     this->head = src;
  152.   }
  153.   
  154.   ~LocalDataBuffer(){
  155.     src = this->head;
  156.   }
  157. private:
  158.   typename DataBuffer<sz>::Head & src;
  159. };
  160. template<Uint32 sz>
  161. inline
  162. DataBuffer<sz>::Head::Head(){
  163.   used = 0;
  164.   firstItem = RNIL;
  165.   lastItem = RNIL;
  166. }
  167. template<Uint32 sz>
  168. inline
  169. bool DataBuffer<sz>::importable(const DataBufferIterator it, Uint32 len){
  170.   return (it.pos + len < head.used);
  171. }
  172. template<Uint32 sz>
  173. inline
  174. bool DataBuffer<sz>::position(DataBufferIterator& it, Uint32 p){
  175.   // TODO: The current implementation is not the most effective one.
  176.   //       A more effective implementation would start at the current 
  177.   //       position of the iterator.
  178.   if(!first(it)){
  179.     return false;
  180.   }
  181.   return next(it, p);
  182. }
  183.   
  184. template<Uint32 sz>
  185. inline
  186. bool 
  187. DataBuffer<sz>::import(const DataBufferIterator & it, 
  188.        const Uint32* src, Uint32 len){
  189. #if 0
  190.   DataBufferIterator it;
  191.   position(it, _it.pos);
  192.   
  193.   for(; len > 0; len--){
  194.     Uint32 s = * src;
  195.     * it.data = s;
  196.     next(it);
  197.     src++;
  198.   }
  199.   return true;
  200. #else
  201.   Uint32 ind = (it.pos % sz);
  202.   Uint32 left = sz  - ind;
  203.   Segment * p = it.curr.p;
  204.   while(len > left){
  205.     memcpy(&p->data[ind], src, 4 * left);
  206.     src += left;
  207.     len -= left;
  208.     ind = 0;
  209.     left = sz;
  210.     p = thePool.getPtr(p->nextPool);
  211.   }
  212.   
  213.   memcpy(&p->data[ind], src, 4 * len);      
  214.   return true;
  215. #endif
  216. }
  217. template<Uint32 sz>
  218. inline
  219. bool 
  220. DataBuffer<sz>::append(const Uint32* src, Uint32 len){
  221.   if(len == 0)
  222.     return true;
  223.   
  224.   Uint32 pos = head.used;
  225.   if(!seize(len)){
  226.     return false;
  227.   }
  228.   DataBufferIterator it;
  229.   
  230.   if(position(it, pos) && import(it, src, len)){
  231.     return true;
  232.   }
  233.   abort();
  234.   return false;
  235. }
  236. template<Uint32 sz>
  237. inline
  238. void DataBuffer<sz>::print(FILE* out) const {
  239.   fprintf(out, "[DataBuffer used=%d words, segmentsize=%d words",
  240.   head.used, sz);
  241.   if (head.firstItem == RNIL) {
  242.     fprintf(out, ": No segments seized.]n");
  243.     return;
  244.   } else {
  245.     fprintf(out, "n");
  246.   }
  247.   Ptr<Segment> ptr;
  248.   ptr.i = head.firstItem;
  249.   
  250.   Uint32 acc = 0;
  251.   for(; ptr.i != RNIL; ){
  252.     thePool.getPtr(ptr);
  253.     const Uint32 * rest = ptr.p->data;
  254.     for(Uint32 i = 0; i<sz; i++){
  255.       fprintf(out, " H'%.8x", rest[i]);
  256.       if(acc++ == 6){
  257. acc = 0;
  258. fprintf(out, "n");
  259.       }
  260.     }
  261.     ptr.i = ptr.p->nextPool;
  262.   }
  263.   fprintf(out, " ]n");
  264. }
  265. template<Uint32 sz>
  266. inline
  267. DataBuffer<sz>::DataBuffer(DataBufferPool & p) : thePool(p){
  268. }
  269. template<Uint32 sz>
  270. inline
  271. bool
  272. DataBuffer<sz>::seize(Uint32 n){
  273.   Uint32 rest; // Free space in last segment (currently)
  274.   Segment* prevPtr;
  275.   if(head.firstItem == RNIL){
  276.     rest = 0;
  277.     prevPtr = (Segment*)&head.firstItem;
  278.   } else {
  279.     rest = (sz - (head.used % sz)) % sz;
  280.     prevPtr = thePool.getPtr(head.lastItem);
  281.   }
  282.   
  283.   /**
  284.    * Check for space
  285.    */
  286.   Uint32 free = thePool.getNoOfFree() * sz + rest;
  287.   if(n > free){
  288.     release();
  289.     return false;
  290.   }
  291.     
  292.   Uint32 used = head.used + n;
  293.   Ptr<Segment> currPtr; 
  294.   currPtr.i = head.lastItem;
  295.   
  296.   while(n >= sz){
  297.     if(0)
  298.       ndbout_c("n(%d) %c sz(%d)", n, (n>sz?'>':(n<sz?'<':'=')), sz);    
  299.     thePool.seize(currPtr); assert(currPtr.i != RNIL);
  300.     prevPtr->nextPool = currPtr.i;
  301.      
  302.     prevPtr = currPtr.p;
  303.     prevPtr->nextPool = RNIL;
  304.     n -= sz;
  305.   }
  306.   
  307.   if(0){
  308.     Uint32 pos = rest + n;
  309.     ndbout_c("rest(%d), n(%d) pos=%d %c sz(%d)", 
  310.      rest, n, pos, (pos>sz?'>':(pos<sz?'<':'=')), sz);
  311.   }
  312.   
  313.   if(n > rest){
  314.     thePool.seize(currPtr);
  315.     assert(currPtr.i != RNIL);
  316.     prevPtr->nextPool = currPtr.i;
  317.     currPtr.p->nextPool = RNIL;
  318.   }
  319.   
  320.   head.used = used;
  321.   head.lastItem = currPtr.i;
  322.   
  323. #if 0
  324.   {
  325.     ndbout_c("Before validate - %d", head.used);
  326.     if(head.used == 0){
  327.       assert(head.firstItem == RNIL);
  328.       assert(head.lastItem == RNIL);
  329.     } else {
  330.       Ptr<Segment> tmp;
  331.       tmp.i = head.firstItem;
  332.       for(Uint32 i = head.used; i > sz; i -= sz){
  333. ndbout << tmp.i << " ";
  334. tmp.p = thePool.getPtr(tmp.i);
  335. tmp.i = tmp.p->nextPool;
  336.       }
  337.       ndbout_c("%d", tmp.i);
  338.       assert(head.lastItem == tmp.i);
  339.     }
  340.     ndbout_c("After validate");
  341.   }
  342. #endif
  343.   return true;
  344. }
  345. template<Uint32 sz>
  346. inline
  347. void
  348. DataBuffer<sz>::release(){
  349.   Uint32 used = head.used + sz - 1;
  350.   if(head.firstItem != RNIL){
  351.     thePool.releaseList(used / sz, head.firstItem, head.lastItem);
  352.     head.used = 0;
  353.     head.firstItem = RNIL;
  354.     head.lastItem = RNIL;
  355.   }
  356. }
  357. template<Uint32 sz>
  358. inline
  359. Uint32
  360. DataBuffer<sz>::getSegmentSize(){
  361.   return sz;
  362. }
  363. template<Uint32 sz>
  364. inline
  365. bool
  366. DataBuffer<sz>::first(DataBufferIterator & it){
  367.   return first((ConstDataBufferIterator&)it);
  368. }
  369. template<Uint32 sz>
  370. inline
  371. bool
  372. DataBuffer<sz>::next(DataBufferIterator & it){
  373.   return next((ConstDataBufferIterator&)it);
  374. }
  375. template<Uint32 sz>
  376. inline
  377. bool
  378. DataBuffer<sz>::next(DataBufferIterator & it, Uint32 hops){
  379.   return next((ConstDataBufferIterator&)it, hops);
  380. }
  381. template<Uint32 sz>
  382. inline
  383. bool
  384. DataBuffer<sz>::first(ConstDataBufferIterator & it) const {
  385.   it.curr.i = head.firstItem;
  386.   if(it.curr.i == RNIL){
  387.     it.setNull();
  388.     return false;
  389.   }
  390.   thePool.getPtr(it.curr);
  391.   it.data = &it.curr.p->data[0];
  392.   it.ind = 0;
  393.   it.pos = 0;
  394.   return true;
  395. }
  396. template<Uint32 sz>
  397. inline
  398. bool
  399. DataBuffer<sz>::next(ConstDataBufferIterator & it) const {
  400.   it.ind ++;
  401.   it.data ++;
  402.   it.pos ++;
  403.   if(it.ind < sz && it.pos < head.used){
  404.     return true;
  405.   }
  406.   if(it.pos < head.used){
  407.     it.curr.i = it.curr.p->nextPool;
  408. #ifdef ARRAY_GUARD    
  409.     if(it.curr.i == RNIL){
  410.       /**
  411.        * This is actually "internal error"
  412.        * pos can't be less than head.used and at the same time we can't 
  413.        * find next segment
  414.        * 
  415.        * Note this must not "really" be checked since thePool.getPtr will
  416.        *  abort when trying to get RNIL. That's why the check is within
  417.        *  ARRAY_GUARD
  418.        */
  419.       ErrorReporter::handleAssert("DataBuffer<sz>::next", __FILE__, __LINE__);
  420.     }
  421. #endif
  422.     thePool.getPtr(it.curr);
  423.     it.data = &it.curr.p->data[0];
  424.     it.ind = 0;
  425.     return true;
  426.   }
  427.   it.setNull();
  428.   return false;
  429. }
  430. template<Uint32 sz>
  431. inline
  432. bool
  433. DataBuffer<sz>::next(ConstDataBufferIterator & it, Uint32 hops) const {
  434. #if 0
  435.   for (Uint32 i=0; i<hops; i++) {
  436.     if (!this->next(it))
  437.       return false;
  438.   }
  439.   return true;
  440. #else
  441.   if(it.pos + hops < head.used){
  442.     while(hops >= sz){
  443.       it.curr.i = it.curr.p->nextPool;
  444.       thePool.getPtr(it.curr);
  445.       hops -= sz;
  446.       it.pos += sz;
  447.     }
  448.     it.ind += hops;
  449.     it.pos += hops;
  450.     if(it.ind < sz){
  451.       it.data = &it.curr.p->data[it.ind];
  452.       return true;
  453.     }
  454.     
  455.     it.curr.i = it.curr.p->nextPool;
  456.     thePool.getPtr(it.curr);
  457.     it.ind -= sz;
  458.     it.data = &it.curr.p->data[it.ind];
  459.     return true;
  460.   }
  461.   it.setNull();
  462.   return false;
  463. #endif
  464. }
  465. template<Uint32 sz>
  466. inline
  467. Uint32
  468. DataBuffer<sz>::getSize() const {
  469.   return head.used;
  470. }
  471. template<Uint32 sz>
  472. inline
  473. bool
  474. DataBuffer<sz>::isEmpty() const {
  475.   return (head.used == 0);
  476. }
  477. #endif