List:Commits« Previous MessageNext Message »
From:Jonas Oreland Date:May 6 2009 1:16pm
Subject:bzr push into mysql-5.1-telco-7.0-spj branch (jonas:2882 to 2884)
View as plain text  
 2884 Jonas Oreland	2009-05-06
      ndb - spj
        Start using DataBuffer2

    M  storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp
    M  storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
    M  storage/ndb/src/kernel/blocks/record_types.hpp
    M  storage/ndb/src/kernel/vm/ArenaPool.cpp
 2883 Jonas Oreland	2009-05-06
      ndb - Add DataBuffer2 which is DataBuffer but with Pool as template argument

    A  storage/ndb/src/kernel/vm/DataBuffer2.hpp
 2882 Jonas Oreland	2009-05-05
      ndb - spj - fix bug in ArenaPool

    M  storage/ndb/src/kernel/vm/ArenaPool.cpp
    M  storage/ndb/src/kernel/vm/ArenaPool.hpp
=== modified file 'storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2009-05-04 13:01:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2009-05-06 12:18:38 +0000
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite
 #include <AttributeHeader.hpp>
 #include <DLFifoList.hpp>
 #include <ArenaPool.hpp>
+#include <DataBuffer2.hpp>
 
 class SectionReader;
 struct QueryNode;
@@ -65,10 +66,10 @@ protected:
 public:
   struct Request;
   struct TreeNode;
-  typedef DataBuffer<15> Dependency_map;
-  typedef LocalDataBuffer<15> Local_dependency_map;
-  typedef DataBuffer<15> PatternStore;
-  typedef LocalDataBuffer<15> Local_pattern_store;
+  typedef DataBuffer2<14, LocalArenaPoolImpl> Dependency_map;
+  typedef LocalDataBuffer2<14, LocalArenaPoolImpl> Local_dependency_map;
+  typedef DataBuffer2<14, LocalArenaPoolImpl> PatternStore;
+  typedef LocalDataBuffer2<14, LocalArenaPoolImpl> Local_pattern_store;
 
   /**
    * This struct represent a row being passed to a child
@@ -409,13 +410,9 @@ private:
   Request_pool m_request_pool;
   Request_hash m_scan_request_hash;
   Request_hash m_lookup_request_hash;
+  ArenaPool m_dependency_map_pool;
   TreeNode_pool m_treenode_pool;
 
-  /**
-   * TODO, make arena-variant of DataBuffer
-   */
-  Dependency_map::DataBufferPool m_dependency_map_pool;
-
   void do_init(Request*, const struct LqhKeyReq*, Uint32 senderRef);
   void store_lookup(Ptr<Request>);
   void handle_early_lqhkey_ref(Signal*, const LqhKeyReq *, Uint32 err);
@@ -442,7 +439,7 @@ private:
   void start(Signal*, Ptr<Request>, SegmentedSectionPtr);
   void nodeFinished(Signal* signal, Ptr<Request>, Ptr<TreeNode>);
   void cleanup(Ptr<Request>);
-  void cleanup_common(Ptr<TreeNode>);
+  void cleanup_common(Ptr<Request>, Ptr<TreeNode>);
 
   /**
    * Misc

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2009-05-04 13:01:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2009-05-06 12:18:38 +0000
@@ -63,7 +63,10 @@ void Dbspj::execREAD_CONFIG_REQ(Signal* 
   m_treenode_pool.arena_pool_init(&m_arenaAllocator, RT_SPJ_TREENODE, pc);
   m_lookup_request_hash.setSize(16);
   m_scan_request_hash.setSize(16);
-  m_dependency_map_pool.setSize(16);
+
+  Record_info ri;
+  Dependency_map::createRecordInfo(ri, RT_SPJ_DATABUFFER);
+  m_dependency_map_pool.init(&m_arenaAllocator, ri, pc);
 
   ReadConfigConf* const conf = 
     reinterpret_cast<ReadConfigConf*>(signal->getDataPtrSend());
@@ -77,22 +80,93 @@ void Dbspj::execREAD_CONFIG_REQ(Signal* 
 
 void Dbspj::execSTTOR(Signal* signal) 
 {
+//#define UNIT_TEST_DATABUFFER2
+
   jamEntry();
   /* START CASE */
-  // const Uint16 tphase = signal->theData[1];
+  const Uint16 tphase = signal->theData[1];
+
   ndbout << "Dbspj::execSTTOR() inst:" << instance() 
-	 << " phase=" << signal->theData[1] << endl;
+	 << " phase=" << tphase << endl;
   const Uint16 csignalKey = signal->theData[6];
   signal->theData[0] = csignalKey;
   signal->theData[1] = 3;    /* BLOCK CATEGORY */
   signal->theData[2] = 2;    /* SIGNAL VERSION NUMBER */
-  signal->theData[3] = 255;  /* Start phase end*/
-  //signal->theData[4] = 255;
+#ifdef UNIT_TEST_DATABUFFER2
+  signal->theData[3] = 120;  /* Start phase end*/
+#else
+  signal->theData[3] = 255;
+#endif
+  signal->theData[4] = 255;
   if(isNdbMtLqh()){
     sendSignal(DBSPJ_REF, GSN_STTORRY, signal, 5, JBB);
   }else{
     sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
   }
+
+#ifdef UNIT_TEST_DATABUFFER2
+  if (tphase == 120)
+  {
+    ndbout_c("basic test of ArenaPool / DataBuffer2");
+
+    for (Uint32 i = 0; i<100; i++)
+    {
+      ArenaHead ah;
+      if (!m_arenaAllocator.seize(ah))
+      {
+        ndbout_c("Failed to allocate arena");
+        break;
+      }
+
+      ndbout_c("*** LOOP %u", i);
+      Uint32 sum = 0;
+      Dependency_map::Head head;
+      LocalArenaPoolImpl pool(ah, m_dependency_map_pool);
+      for (Uint32 j = 0; j<100; j++)
+      {
+        Uint32 sz = rand() % 1000;
+        if (0)
+          ndbout_c("adding %u", sz);
+        Local_dependency_map list(pool, head);
+        for (Uint32 i = 0; i<sz; i++)
+          signal->theData[i] = sum + i;
+        list.append(signal->theData, sz);
+        sum += sz;
+      }
+
+      {
+        ndbrequire(head.getSize() == sum);
+        Local_dependency_map list(pool, head);
+        Dependency_map::ConstDataBufferIterator it;
+        Uint32 cnt = 0;
+        for (list.first(it); !it.isNull(); list.next(it))
+        {
+          ndbrequire(* it.data == cnt);
+          cnt++;
+        }
+
+        ndbrequire(cnt == sum);
+      }
+
+      Resource_limit rl;
+      if (m_ctx.m_mm.get_resource_limit(7, rl))
+      {
+        ndbout_c("Resource %d min: %d max: %d curr: %d",
+                 7, rl.m_min, rl.m_max, rl.m_curr);
+      }
+
+      {
+        ndbout_c("release map");
+        Local_dependency_map list(pool, head);
+        list.release();
+      }
+
+      ndbout_c("release all");
+      m_arenaAllocator.release(ah);
+      ndbout_c("*** LOOP %u sum: %u", i, sum);
+    }
+  }
+#endif
 }//Dbspj::execSTTOR()
 
 /**
@@ -703,25 +777,23 @@ Dbspj::cleanup(Ptr<Request> requestPtr)
 }
 
 void
-Dbspj::cleanup_common(Ptr<TreeNode> treeNodePtr)
+Dbspj::cleanup_common(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr)
 {
   jam();
 
+  LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
   {
-    Local_dependency_map list(m_dependency_map_pool,
-                              treeNodePtr.p->m_dependent_nodes);
+    Local_dependency_map list(pool, treeNodePtr.p->m_dependent_nodes);
     list.release();
   }
 
   {
-    Local_pattern_store pattern(m_dependency_map_pool,
-                                treeNodePtr.p->m_keyPattern);
+    Local_pattern_store pattern(pool, treeNodePtr.p->m_keyPattern);
     pattern.release();
   }
 
   {
-    Local_pattern_store pattern(m_dependency_map_pool,
-                                treeNodePtr.p->m_attrParamPattern);
+    Local_pattern_store pattern(pool, treeNodePtr.p->m_attrParamPattern);
     pattern.release();
   }
 
@@ -1226,8 +1298,8 @@ Dbspj::lookup_execTRANSID_AI(Signal* sig
   jam();
 
   {
-    Local_dependency_map list(m_dependency_map_pool,
-                              treeNodePtr.p->m_dependent_nodes);
+    LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+    Local_dependency_map list(pool, treeNodePtr.p->m_dependent_nodes);
     Dependency_map::ConstDataBufferIterator it;
     for (list.first(it); !it.isNull(); list.next(it))
     {
@@ -1339,8 +1411,8 @@ Dbspj::lookup_start_child(Signal* signal
       /**
        * Get key-pattern
        */
-      Local_pattern_store pattern(m_dependency_map_pool,
-                                  treeNodePtr.p->m_keyPattern);
+      LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+      Local_pattern_store pattern(pool, treeNodePtr.p->m_keyPattern);
 
       err = expand(ptrI, pattern, rowRef.m_row_data.m_section);
       if (unlikely(err != 0))
@@ -1389,7 +1461,7 @@ void
 Dbspj::lookup_cleanup(Ptr<Request> requestPtr,
                       Ptr<TreeNode> treeNodePtr)
 {
-  cleanup_common(treeNodePtr);
+  cleanup_common(requestPtr, treeNodePtr);
 }
 
 
@@ -1742,8 +1814,8 @@ Dbspj::scanFrag_execTRANSID_AI(Signal* s
     treeNodePtr.p->m_scanfrag_data.m_rows_received;
 
   {
-    Local_dependency_map list(m_dependency_map_pool,
-                              treeNodePtr.p->m_dependent_nodes);
+    LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+    Local_dependency_map list(pool, treeNodePtr.p->m_dependent_nodes);
     Dependency_map::ConstDataBufferIterator it;
     for (list.first(it); !it.isNull(); list.next(it))
     {
@@ -1854,7 +1926,7 @@ void
 Dbspj::scanFrag_cleanup(Ptr<Request> requestPtr,
                         Ptr<TreeNode> treeNodePtr)
 {
-  cleanup_common(treeNodePtr);
+  cleanup_common(requestPtr, treeNodePtr);
 }
 /**
  * END - MODULE SCAN FRAG
@@ -2313,8 +2385,8 @@ Dbspj::parseDA(Build_context& ctx,
       {
         DEBUG("adding " << dst[i] << " as parent");
         Ptr<TreeNode> parentPtr = ctx.m_node_list[dst[i]];
-        Local_dependency_map map(m_dependency_map_pool,
-                                 parentPtr.p->m_dependent_nodes);
+        LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+        Local_dependency_map map(pool, parentPtr.p->m_dependent_nodes);
         if (unlikely(!map.append(&treeNodePtr.i, 1)))
         {
           err = DbspjErr::OutOfQueryMemory;
@@ -2343,8 +2415,8 @@ Dbspj::parseDA(Build_context& ctx,
       Uint32 len = len_cnt & 0xFFFF; // length of pattern in words
       Uint32 cnt = len_cnt >> 16;    // no of parameters
 
-      Local_pattern_store pattern(m_dependency_map_pool,
-                                  treeNodePtr.p->m_keyPattern);
+      LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+      Local_pattern_store pattern(pool, treeNodePtr.p->m_keyPattern);
 
       if (cnt)
       {

=== modified file 'storage/ndb/src/kernel/blocks/record_types.hpp'
--- a/storage/ndb/src/kernel/blocks/record_types.hpp	2009-05-04 07:12:52 +0000
+++ b/storage/ndb/src/kernel/blocks/record_types.hpp	2009-05-06 12:18:38 +0000
@@ -90,5 +90,6 @@
 #define RT_SPJ_REQUEST             MAKE_TID( 1, RG_QUERY_MEMORY)
 #define RT_SPJ_TREENODE            MAKE_TID( 2, RG_QUERY_MEMORY)
 #define RT_SPJ_ARENA_BLOCK         MAKE_TID( 3, RG_QUERY_MEMORY)
+#define RT_SPJ_DATABUFFER          MAKE_TID( 4, RG_QUERY_MEMORY)
 
 #endif

=== modified file 'storage/ndb/src/kernel/vm/ArenaPool.cpp'
--- a/storage/ndb/src/kernel/vm/ArenaPool.cpp	2009-05-05 13:15:52 +0000
+++ b/storage/ndb/src/kernel/vm/ArenaPool.cpp	2009-05-06 12:18:38 +0000
@@ -119,6 +119,10 @@ ArenaPool::seize(ArenaHead & ah, Ptr<voi
   Uint32 sz = m_record_info.m_size;
   Uint32 off = m_record_info.m_offset_magic;
 
+  if (0)
+    ndbout_c("pos: %u sz: %u (sum: %u) bs: %u",
+             pos, sz, (pos + sz), bs);
+
   if (pos + sz <= bs)
   {
     /**

=== added file 'storage/ndb/src/kernel/vm/DataBuffer2.hpp'
--- a/storage/ndb/src/kernel/vm/DataBuffer2.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/vm/DataBuffer2.hpp	2009-05-06 12:15:41 +0000
@@ -0,0 +1,563 @@
+/* Copyright (C) 2003 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef DATA_BUFFER2_HPP
+#define DATA_BUFFER2_HPP
+
+/**
+ * @class  DataBuffer
+ * @brief  Buffer of data words
+ *
+ * @note   The buffer is divided into segments (of size sz)
+ */
+template <Uint32 sz, typename Pool>
+class DataBuffer2 {
+public:
+  struct Segment {
+    Uint32 magic;
+    Uint32 nextPool;
+    Uint32 data[sz];
+    NdbOut& print(NdbOut& out){
+      out << "[DataBuffer<" << sz << ">::Segment this="
+	  << this << dec << " nextPool= "
+	  << nextPool << " ]";
+      return out;
+    }
+  };
+public:
+  typedef Pool DataBufferPool;
+
+  /**
+   * Head/anchor for data buffer
+   */
+  struct Head {
+    Head() ;
+
+    Uint32 used;       // Words used
+    Uint32 firstItem;  // First segment (or RNIL)
+    Uint32 lastItem;   // Last segment (or RNIL)
+
+    /**
+     * Get size of databuffer, in words
+     */
+    Uint32 getSize() const { return used;}
+
+    /**
+     * Get segment size in words (template argument)
+     */
+    static Uint32 getSegmentSize() { return sz;}
+  };
+
+  /** Constructor */
+  DataBuffer2(DataBufferPool &);
+
+  /** Seize <b>n</b> words, Release */
+  bool seize(Uint32 n);
+  void release();
+
+  /**
+   * Get size of databuffer, in words
+   */
+  Uint32 getSize() const;
+
+  /**
+   * Check if buffer is empty
+   */
+  bool isEmpty() const;
+
+  /**
+   * Get segment size in words (template argument)
+   */
+  static Uint32 getSegmentSize();
+
+  void print(FILE*) const;
+
+  /* ----------------------------------------------------------------------- */
+
+  struct DataBufferIterator {
+    Ptr<Segment>       curr;  // Ptr to current segment
+    Uint32*            data;  // Pointer to current data (word)
+    Uint32             ind;   // Word index within a segment
+    Uint32             pos;   // Absolute word position within DataBuffer
+
+    void print(FILE* out) {
+      fprintf(out, "[DataBufferIterator curr.i=%d, data=%p, ind=%d, pos=%d]\n",
+	      curr.i, (void*) data, ind, pos);
+    };
+
+    inline bool isNull() const { return curr.isNull();}
+    inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
+  };
+  typedef DataBufferIterator Iterator;
+
+  struct ConstDataBufferIterator {
+    ConstPtr<Segment>  curr;
+    const Uint32 *     data;
+    Uint32             ind;
+    Uint32             pos;
+
+    inline bool isNull() const { return curr.isNull();}
+    inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
+  };
+
+  /**
+   * Iterator
+   * @parameter hops  Number of words to jump forward
+   * @note DataBuffer::next returns false if applied to last word.
+   */
+  bool first(DataBufferIterator &);
+  bool next(DataBufferIterator &);
+  bool next(DataBufferIterator &, Uint32 hops);
+  bool nextPool(DataBufferIterator &);
+
+  /**
+   * Set iterator to position
+   */
+  bool position(DataBufferIterator& it, Uint32 pos);
+
+  /** Iterator */
+  bool first(ConstDataBufferIterator &) const;
+  bool next(ConstDataBufferIterator &) const;
+  bool next(ConstDataBufferIterator &, Uint32 hops) const;
+  bool nextPool(ConstDataBufferIterator &) const;
+
+  /**
+   * Returns true if it is possible to store <em>len</em>
+   * no of words at position given in iterator.
+   */
+  bool importable(const DataBufferIterator, Uint32 len);
+
+  /**
+   * Stores <em>len</em> no of words starting at location <em>src</em> in
+   * databuffer at position given in iterator.
+   *
+   * @return true if success, false otherwise.
+   * @note Iterator is not advanced.
+   */
+  bool import(const DataBufferIterator &, const Uint32* src, Uint32 len);
+
+  /**
+   * Increases size with appends <em>len</em> words
+   * @return true if success, false otherwise.
+   */
+  bool append(const Uint32* src, Uint32 len);
+
+  static void createRecordInfo(Record_info & ri, Uint32 type_id);
+protected:
+  Head head;
+  DataBufferPool &  thePool;
+
+private:
+  /**
+   * This is NOT a public method, since the intension is that the import
+   * method using iterators will be more effective in the future
+   */
+  bool import(Uint32 pos, const Uint32* src, Uint32 len);
+};
+
+template<Uint32 sz, typename Pool>
+class LocalDataBuffer2 : public DataBuffer2<sz, Pool> {
+public:
+  LocalDataBuffer2(typename DataBuffer2<sz, Pool>::DataBufferPool & thePool,
+                   typename DataBuffer2<sz, Pool>::Head & _src)
+    : DataBuffer2<sz, Pool>(thePool), src(_src)
+  {
+    this->head = src;
+  }
+
+  ~LocalDataBuffer2(){
+    src = this->head;
+  }
+private:
+  typename DataBuffer2<sz, Pool>::Head & src;
+};
+
+template<Uint32 sz, typename Pool>
+inline
+DataBuffer2<sz, Pool>::Head::Head(){
+  used = 0;
+  firstItem = RNIL;
+  lastItem = RNIL;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool DataBuffer2<sz, Pool>::importable(const DataBufferIterator it, Uint32 len){
+  return (it.pos + len < head.used);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool DataBuffer2<sz, Pool>::position(DataBufferIterator& it, Uint32 p){
+
+  // TODO: The current implementation is not the most effective one.
+  //       A more effective implementation would start at the current
+  //       position of the iterator.
+
+  if(!first(it)){
+    return false;
+  }
+  return next(it, p);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::import(const DataBufferIterator & it,
+                              const Uint32* src, Uint32 len)
+{
+  Uint32 ind = (it.pos % sz);
+  Uint32 left = sz  - ind;
+  Segment * p = it.curr.p;
+
+  if (left)
+  {
+    memcpy(p->data+ind, src, 4 * left);
+    if (len <= left)
+      return true;
+
+    src += left;
+    len -= left;
+  }
+
+  while (len > sz)
+  {
+    p = static_cast<Segment*>(thePool.getPtr(p->nextPool));
+    memcpy(p->data, src, 4 * sz);
+    src += sz;
+    len -= sz;
+  }
+
+  if (len)
+  {
+    p = static_cast<Segment*>(thePool.getPtr(p->nextPool));
+    memcpy(p->data, src, 4 * len);
+  }
+
+  return true;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::append(const Uint32* src, Uint32 len){
+  if(len == 0)
+    return true;
+
+  Uint32 pos = head.used;
+  if(!seize(len)){
+    return false;
+  }
+  DataBufferIterator it;
+
+  if(position(it, pos) && import(it, src, len)){
+    return true;
+  }
+  abort();
+  return false;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+void DataBuffer2<sz, Pool>::print(FILE* out) const {
+  fprintf(out, "[DataBuffer used=%d words, segmentsize=%d words",
+	  head.used, sz);
+
+  if (head.firstItem == RNIL) {
+    fprintf(out, ": No segments seized.]\n");
+    return;
+  } else {
+    fprintf(out, "\n");
+  }
+
+  Ptr<Segment> ptr;
+  ptr.i = head.firstItem;
+
+  Uint32 acc = 0;
+  for(; ptr.i != RNIL; ){
+    thePool.getPtr(ptr);
+    const Uint32 * rest = ptr.p->data;
+    for(Uint32 i = 0; i<sz; i++){
+      fprintf(out, " H'%.8x", rest[i]);
+      if(acc++ == 6){
+	acc = 0;
+	fprintf(out, "\n");
+      }
+    }
+    ptr.i = ptr.p->nextPool;
+  }
+  fprintf(out, " ]\n");
+}
+
+template<Uint32 sz, typename Pool>
+inline
+DataBuffer2<sz, Pool>::DataBuffer2(DataBufferPool & p) : thePool(p){
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::seize(Uint32 n){
+  Uint32 rest; // Free space in last segment (currently)
+
+  if(head.firstItem == RNIL)
+  {
+    rest = 0;
+  }
+  else
+  {
+    rest = (sz - (head.used % sz)) % sz;
+  }
+
+  if (0)
+    ndbout_c("seize(%u) used: %u rest: %u firstItem: 0x%x",
+             n, head.used, rest, head.firstItem);
+
+  if (rest >= n)
+  {
+    head.used += n;
+    return true;
+  }
+
+  Uint32 used = head.used + n;
+  Segment first;
+  Ptr<Segment> currPtr;
+  currPtr.p = &first;
+  first.nextPool = RNIL;
+
+  while (n >= sz)
+  {
+    Ptr<void> tmp;
+    if (thePool.seize(tmp))
+    {
+      currPtr.p->nextPool = tmp.i;
+      currPtr.i = tmp.i;
+      currPtr.p = static_cast<Segment*>(tmp.p);
+    }
+    else
+    {
+      goto error;
+    }
+    n -= sz;
+  }
+
+  if(n > rest)
+  {
+    Ptr<void> tmp;
+    if (thePool.seize(tmp))
+    {
+      currPtr.p->nextPool = tmp.i;
+      currPtr.i = tmp.i;
+      currPtr.p = static_cast<Segment*>(tmp.p);
+    }
+    else
+    {
+      goto error;
+    }
+  }
+
+  if (head.firstItem == RNIL)
+  {
+    head.firstItem = first.nextPool;
+  }
+  else
+  {
+    Segment* lastPtr = static_cast<Segment*>(thePool.getPtr(head.lastItem));
+    lastPtr->nextPool = first.nextPool;
+  }
+
+  head.used = used;
+  head.lastItem = currPtr.i;
+  currPtr.p->nextPool = RNIL;
+  return true;
+
+error:
+  currPtr.i = first.nextPool;
+  while (currPtr.i != RNIL)
+  {
+    currPtr.p = static_cast<Segment*>(thePool.getPtr(currPtr.i));
+    Ptr<void> tmp;
+    tmp.i = currPtr.i;
+    tmp.p = currPtr.p;
+    currPtr.i = currPtr.p->nextPool;
+    thePool.release(tmp);
+  }
+  return false;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+void
+DataBuffer2<sz, Pool>::release(){
+  Ptr<void> tmp;
+  tmp.i = head.firstItem;
+  while (tmp.i != RNIL)
+  {
+    tmp.p = thePool.getPtr(tmp.i);
+    Uint32 next = static_cast<Segment*>(tmp.p)->nextPool;
+    thePool.release(tmp);
+    tmp.i = next;
+  }
+}
+
+template<Uint32 sz, typename Pool>
+inline
+Uint32
+DataBuffer2<sz, Pool>::getSegmentSize(){
+  return sz;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::first(DataBufferIterator & it){
+  return first((ConstDataBufferIterator&)it);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(DataBufferIterator & it){
+  return next((ConstDataBufferIterator&)it);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(DataBufferIterator & it, Uint32 hops){
+  return next((ConstDataBufferIterator&)it, hops);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::first(ConstDataBufferIterator & it) const {
+  it.curr.i = head.firstItem;
+  if(it.curr.i == RNIL){
+    it.setNull();
+    return false;
+  }
+  it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+  it.data = &it.curr.p->data[0];
+  it.ind = 0;
+  it.pos = 0;
+  return true;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(ConstDataBufferIterator & it) const {
+  it.ind ++;
+  it.data ++;
+  it.pos ++;
+  if(it.ind < sz && it.pos < head.used){
+    return true;
+  }
+
+  if(it.pos < head.used){
+    it.curr.i = it.curr.p->nextPool;
+#ifdef ARRAY_GUARD
+    if(it.curr.i == RNIL){
+      /**
+       * This is actually "internal error"
+       * pos can't be less than head.used and at the same time we can't
+       * find next segment
+       *
+       * Note this must not "really" be checked since thePool.getPtr will
+       *  abort when trying to get RNIL. That's why the check is within
+       *  ARRAY_GUARD
+       */
+      ErrorReporter::handleAssert("DataBuffer2<sz, Pool>::next", __FILE__, __LINE__);
+    }
+#endif
+    it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+    it.data = &it.curr.p->data[0];
+    it.ind = 0;
+    return true;
+  }
+  it.setNull();
+  return false;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(ConstDataBufferIterator & it, Uint32 hops) const {
+#if 0
+  for (Uint32 i=0; i<hops; i++) {
+    if (!this->next(it))
+      return false;
+  }
+  return true;
+#else
+  if(it.pos + hops < head.used){
+    while(hops >= sz){
+      it.curr.i = it.curr.p->nextPool;
+      it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+      hops -= sz;
+      it.pos += sz;
+    }
+
+    it.ind += hops;
+    it.pos += hops;
+    if(it.ind < sz){
+      it.data = &it.curr.p->data[it.ind];
+      return true;
+    }
+
+    it.curr.i = it.curr.p->nextPool;
+    it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+    it.ind -= sz;
+    it.data = &it.curr.p->data[it.ind];
+    return true;
+  }
+  it.setNull();
+  return false;
+#endif
+}
+
+template<Uint32 sz, typename Pool>
+inline
+Uint32
+DataBuffer2<sz, Pool>::getSize() const {
+  return head.used;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::isEmpty() const {
+  return (head.used == 0);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+void
+DataBuffer2<sz, Pool>::createRecordInfo(Record_info & ri, Uint32 type_id)
+{
+  Segment tmp;
+  const char * off_base = (char*)&tmp;
+  const char * off_next = (char*)&tmp.nextPool;
+  const char * off_magic = (char*)&tmp.magic;
+
+  ri.m_size = sizeof(tmp);
+  ri.m_offset_next_pool = Uint32(off_next - off_base);
+  ri.m_offset_magic = Uint32(off_magic - off_base);
+  ri.m_type_id = type_id;
+}
+
+#endif
+


Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20090506121838-4vlwcwguuke3u3qa.bundle
Thread
bzr push into mysql-5.1-telco-7.0-spj branch (jonas:2882 to 2884)Jonas Oreland6 May