List:Commits« Previous MessageNext Message »
From:Ole John Aske Date:November 8 2012 12:05pm
Subject:bzr push into mysql-5.1-telco-7.1 branch (ole.john.aske:4653 to 4654)
View as plain text  
 4654 Ole John Aske	2012-11-08 [merge]
      Merge 7.0 -> 7.1

    modified:
      storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp
      storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
 4653 magnus.blaudd@stripped	2012-11-07 [merge]
      Merge 7.0 -> 7.1

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp'

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2012-09-19 06:38:56 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2012-11-08 11:58:49 +0000
@@ -152,6 +152,12 @@
   };
   typedef Ptr<TableRecord> TableRecordPtr;
 
+  enum Buffer_type {
+    BUFFER_VOID  = 0,
+    BUFFER_STACK = 1,
+    BUFFER_VAR   = 2
+  };
+
   struct RowRef
   {
     Uint32 m_page_id;
@@ -159,7 +165,7 @@
     union
     {
       Uint16 unused;
-      Uint16 m_allocator;
+      enum Buffer_type m_alloc_type:16;
     };
 
     void copyto_link(Uint32 * dst) const {
@@ -198,7 +204,6 @@
   struct RowPtr
   {
     Uint32 m_type;
-    Uint32 m_src_node_no;
     Uint32 m_src_node_ptrI;
     Uint32 m_src_correlation;
 
@@ -234,8 +239,26 @@
     };
   };
 
-  struct SLFifoRowList
-  {
+  struct RowBuffer;  // forward decl.
+
+  /**
+   * Define overlayed 'base class' for SLFifoRowList and RowMap.
+   * As we want these to be POD struct, we does not use 
+   * inheritance, but have to take care that first part
+   * of these struct are correctly overlayed.
+   */
+  struct RowCollectionBase
+  {
+    RowBuffer* m_rowBuffer;
+  };
+
+  struct SLFifoRowList //: public RowCollectionBase
+  {
+    /**
+     * BEWARE: Overlayed 'struct RowCollectionBase'
+     */
+    RowBuffer* m_rowBuffer;
+
     /**
      * Data used for a single linked list of rows
      */
@@ -244,13 +267,22 @@
     Uint16 m_first_row_page_pos;
     Uint16 m_last_row_page_pos;
 
+    void construct(RowBuffer& rowBuffer) {
+      m_rowBuffer = &rowBuffer;
+      init();
+    }
     void init() { m_first_row_page_id = RNIL;}
     bool isNull() const { return m_first_row_page_id == RNIL; }
   };
 
-  struct RowMap
+  struct RowMap //: public RowCollectionBase
   {
     /**
+     * BEWARE: Overlayed 'struct RowCollectionBase'
+     */
+    RowBuffer* m_rowBuffer;
+
+    /**
      * Data used for a map with rows (key is correlation id)
      *   currently a single array is used to store row references
      *   (size == batch size)
@@ -259,7 +291,18 @@
     Uint16 m_size;                // size of array
     Uint16 m_elements;            // #elements in array
 
-    void init() { m_map_ref.setNull();}
+    void construct(RowBuffer& rowBuffer,
+                   Uint32 capacity)
+    {
+      m_rowBuffer = &rowBuffer;
+      m_size = capacity;
+      init();
+    }
+    void init() {
+      m_map_ref.setNull();
+      m_elements = 0;
+    }
+
     bool isNull() const { return m_map_ref.isNull(); }
 
     void assign (RowRef ref) {
@@ -296,36 +339,112 @@
     STATIC_CONST( MAP_SIZE_PER_REF_16 = 3 );
   };
 
-  struct SLFifoRowListIterator
-  {
-    RowRef m_ref;
-    Uint32 * m_row_ptr;
-
-    bool isNull() const { return m_ref.isNull(); }
-    void setNull() { m_ref.setNull(); }
-  };
-
-  struct SLFifoRowListIteratorPtr
-  {
-    RowRef m_ref;
-  };
-
-  struct RowMapIterator
-  {
-    Uint32 * m_row_ptr;
+  /**
+   * Define overlayed 'base class' for SLFifoRowListIterator
+   * and RowMapIterator.
+   * As we want these to be POD struct, we does not use 
+   * inheritance, but have to take care that first part
+   * of these struct are correctly overlayed.
+   */
+  struct RowIteratorBase
+  {
+    RowRef m_ref;
+    Uint32 * m_row_ptr;
+
+    bool isNull() const { return m_ref.isNull(); }
+    void setNull() { m_ref.setNull(); }
+  };
+
+  struct SLFifoRowListIterator //: public RowIteratorBase
+  {
+    /**
+     * BEWARE: Overlayed 'struct RowIteratorBase'
+     */
+    RowRef m_ref;
+    Uint32 * m_row_ptr;
+
+    bool isNull() const { return m_ref.isNull(); }
+    void setNull() { m_ref.setNull(); }
+    // END: RowIteratorBase
+  };
+
+  struct RowMapIterator //: public RowIteratorBase
+  {
+    /**
+     * BEWARE: Overlayed 'struct RowIteratorBase'
+     */
+    RowRef m_ref;
+    Uint32 * m_row_ptr;
+
+    bool isNull() const { return m_ref.isNull(); }
+    void setNull() { m_ref.setNull(); }
+    // END: RowIteratorBase
+
     Uint32 * m_map_ptr;
-    RowRef m_ref; // position of actual row
     Uint16 m_size;
     Uint16 m_element_no;
-    bool isNull() const { return m_ref.isNull(); }
-    void setNull() { m_ref.setNull(); }
-  };
-
-  struct RowMapIteratorPtr
-  {
-    Uint32 m_element_no;
-  };
-
+  };
+
+  /**
+   * Abstraction of SLFifoRowList & RowMap
+   */
+  struct RowCollection
+  {
+    enum collection_type
+    {
+      COLLECTION_VOID,
+      COLLECTION_MAP,
+      COLLECTION_LIST
+    };
+    union
+    {
+      RowCollectionBase m_base;  // Common part for map & list
+      SLFifoRowList m_list;
+      RowMap m_map;
+    };
+
+    RowCollection() : m_type(COLLECTION_VOID) {}
+
+    void construct(collection_type type,
+                   RowBuffer& rowBuffer,
+                   Uint32 capacity)
+    {
+      m_type = type;
+      if (m_type == COLLECTION_MAP)
+        m_map.construct(rowBuffer,capacity);
+      else if (m_type == COLLECTION_LIST)
+        m_list.construct(rowBuffer);
+    }
+
+    void init() {
+      if (m_type == COLLECTION_MAP)
+        m_map.init();
+      else if (m_type == COLLECTION_LIST)
+        m_list.init();
+    }
+
+    Uint32 rowOffset() const {
+      return (m_type == COLLECTION_MAP) ? 0 : 2;
+    }
+
+    collection_type m_type;
+  };
+
+  struct RowIterator
+  {
+    union
+    {
+      RowIteratorBase m_base;  // Common part for map & list
+      SLFifoRowListIterator m_list;
+      RowMapIterator m_map;
+    };
+    RowCollection::collection_type m_type;
+
+    RowIterator() { init(); }
+    void init() { m_base.setNull(); }
+    bool isNull() const { return m_base.isNull(); }
+  };
+ 
 
   /**
    * A struct used when building an TreeNode
@@ -368,11 +487,24 @@
 
   struct RowBuffer
   {
-    RowBuffer() { stack_init(); }
+    enum Buffer_type m_type;
+
+    RowBuffer() : m_type(BUFFER_VOID) {}
     DLFifoList<RowPage>::Head m_page_list;
 
-    void stack_init() { new (&m_page_list) DLFifoList<RowPage>::Head(); m_stack.m_pos = 0xFFFF; }
-    void var_init() { new (&m_page_list) DLFifoList<RowPage>::Head(); m_var.m_free = 0; }
+    void init(enum Buffer_type type)
+    {
+      new (&m_page_list) DLFifoList<RowPage>::Head();
+      m_type = type;
+      reset();
+    }
+    void reset()
+    {
+      if (m_type == BUFFER_STACK)
+        m_stack.m_pos = 0xFFFF;
+      else if (m_type == BUFFER_VAR)
+        m_var.m_free = 0;
+    }
 
     struct Stack
     {
@@ -840,11 +972,7 @@
     /**
      * Rows buffered by this node
      */
-    union
-    {
-      RowMap m_row_map;
-      SLFifoRowList m_row_list;
-    };
+    RowCollection m_rows;
 
     union
     {
@@ -892,7 +1020,7 @@
       RT_SCAN                = 0x1  // unbounded result set, scan interface
       ,RT_ROW_BUFFERS        = 0x2  // Do any of the node use row-buffering
       ,RT_MULTI_SCAN         = 0x4  // Is there several scans in request
-      ,RT_VAR_ALLOC          = 0x8  // Is var-allocation used for row-buffer
+//    ,RT_VAR_ALLOC          = 0x8  // DEPRECATED
       ,RT_NEED_PREPARE       = 0x10 // Does any node need m_prepare hook
       ,RT_NEED_COMPLETE      = 0x20 // Does any node need m_complete hook
       ,RT_REPEAT_SCAN_RESULT = 0x40 // Repeat bushy scan result when required
@@ -1122,6 +1250,7 @@
    */
   const OpInfo* getOpInfo(Uint32 op);
   Uint32 build(Build_context&,Ptr<Request>,SectionReader&,SectionReader&);
+  Uint32 initRowBuffers(Ptr<Request>);
   void checkPrepareComplete(Signal*, Ptr<Request>, Uint32 cnt);
   void start(Signal*, Ptr<Request>);
   void checkBatchComplete(Signal*, Ptr<Request>, Uint32 cnt);
@@ -1138,7 +1267,6 @@
   void releaseScanBuffers(Ptr<Request> requestPtr);
   void releaseRequestBuffers(Ptr<Request> requestPtr, bool reset);
   void releaseNodeRows(Ptr<Request> requestPtr, Ptr<TreeNode>);
-  void releaseRow(Ptr<Request>, RowRef ref);
   void registerActiveCursor(Ptr<Request>, Ptr<TreeNode>);
   void nodeFail_checkRequests(Signal*);
   void cleanup_common(Ptr<Request>, Ptr<TreeNode>);
@@ -1146,31 +1274,37 @@
   /**
    * Row buffering
    */
-  Uint32 storeRow(Ptr<Request>, Ptr<TreeNode>, RowPtr &row);
+  Uint32 storeRow(RowCollection& collection, RowPtr &row);
+  void releaseRow(RowCollection& collection, RowRef ref);
   Uint32* stackAlloc(RowBuffer& dst, RowRef&, Uint32 len);
   Uint32* varAlloc(RowBuffer& dst, RowRef&, Uint32 len);
-
-  void add_to_list(SLFifoRowList & list, RowRef rowref);
-  Uint32 add_to_map(Ptr<Request> requestPtr, Ptr<TreeNode>, Uint32, RowRef);
-  Uint32 * get_row_ptr(const RowMap&, RowMapIterator pos);
-  void setupRowPtr(Ptr<TreeNode>, RowPtr& dst, RowRef, const Uint32 * src);
-
-  // NOTE: ref contains info about it being stack/var
-  // so adding an inline would be nice...but that remove possibility
-  // to add jam()'s
-  Uint32 * get_row_ptr_stack(RowRef pos);
-  Uint32 * get_row_ptr_var(RowRef pos);
+  Uint32* rowAlloc(RowBuffer& dst, RowRef&, Uint32 len);
+
+  void add_to_list(SLFifoRowList & list, RowRef);
+  Uint32 add_to_map(RowMap& map, Uint32, RowRef);
+
+  void setupRowPtr(const RowCollection& collection,
+                   RowPtr& dst, RowRef, const Uint32 * src);
+  Uint32 * get_row_ptr(RowRef pos);
 
   /**
    * SLFifoRowListIterator
    */
-  bool first(Ptr<Request>, Ptr<TreeNode>, SLFifoRowListIterator&);
+  bool first(const SLFifoRowList& list, SLFifoRowListIterator&);
   bool next(SLFifoRowListIterator&);
-  bool next(Ptr<Request>, Ptr<TreeNode>, SLFifoRowListIterator&, SLFifoRowListIteratorPtr);
 
-  bool first(Ptr<Request>, Ptr<TreeNode>, RowMapIterator&);
+  /**
+   * RowMapIterator
+   */
+  bool first(const RowMap& map, RowMapIterator&);
   bool next(RowMapIterator&);
-  bool next(Ptr<Request>,Ptr<TreeNode>, RowMapIterator&, RowMapIteratorPtr);
+
+  /**
+   * RowIterator:
+   * Abstraction which may iterate either a RowList or Map
+   */
+  bool first(const RowCollection&, RowIterator&);
+  bool next(RowIterator&);
 
   /**
    * Misc

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2012-10-05 07:42:50 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2012-11-08 11:58:49 +0000
@@ -44,34 +44,31 @@
 #include <signaldata/ReadNodesConf.hpp>
 #include <signaldata/SignalDroppedRep.hpp>
 
-// Use DEBUG to print messages that should be
-// seen only when we debug the product
-
 #ifdef VM_TRACE
 
+/**
+ * DEBUG options for different parts od SPJ block
+ * Comment out those part you don't want DEBUG'ed.
+ */
 #define DEBUG(x) ndbout << "DBSPJ: "<< x << endl;
-#define DEBUG_DICT(x) ndbout << "DBSPJ: "<< x << endl;
-#define DEBUG_LQHKEYREQ
-#define DEBUG_SCAN_FRAGREQ
-
-#else
-
+//#define DEBUG_DICT(x) ndbout << "DBSPJ: "<< x << endl;
+//#define DEBUG_LQHKEYREQ
+//#define DEBUG_SCAN_FRAGREQ
+#endif
+
+/**
+ * Provide empty defs for those DEBUGs which has to be defined.
+ */
+#if !defined(DEBUG)
 #define DEBUG(x)
+#endif
+
+#if !defined(DEBUG_DICT)
 #define DEBUG_DICT(x)
-
 #endif
 
 #define DEBUG_CRASH() ndbassert(false)
 
-#if 1
-#undef DEBUG
-#define DEBUG(x)
-#undef DEBUG_DICT
-#define DEBUG_DICT(x)
-#undef DEBUG_LQHKEYREQ
-#undef DEBUG_SCAN_FRAGREQ
-#endif
-
 const Ptr<Dbspj::TreeNode> Dbspj::NullTreeNodePtr = { 0, RNIL };
 const Dbspj::RowRef Dbspj::NullRowRef = { RNIL, GLOBAL_PAGE_SIZE_WORDS, { 0 } };
 
@@ -1289,54 +1286,92 @@
   }
   requestPtr.p->m_node_cnt = ctx.m_cnt;
 
-  /**
-   * Init ROW_BUFFERS for those TreeNodes requiring either
-   * T_ROW_BUFFER or T_ROW_BUFFER_MAP.
-   */
-  if (requestPtr.p->m_bits & Request::RT_ROW_BUFFERS)
-  {
-    Ptr<TreeNode> treeNodePtr;
-    Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
-    for (list.first(treeNodePtr); !treeNodePtr.isNull(); list.next(treeNodePtr))
-    {
-      if (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER_MAP)
-      {
-        jam();
-        treeNodePtr.p->m_row_map.init();
-      }
-      else if (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER)
-      {
-        jam();
-        treeNodePtr.p->m_row_list.init();
-      }
-    }
-  }
-
   if (ctx.m_scan_cnt > 1)
   {
     jam();
     requestPtr.p->m_bits |= Request::RT_MULTI_SCAN;
+  }
+
+  // Construct RowBuffers where required
+  err = initRowBuffers(requestPtr);
+  if (unlikely(err != 0))
+  {
+    jam();
+    goto error;
+  }
+
+  return 0;
+
+error:
+  jam();
+  return err;
+}
+
+/**
+ * initRowBuffers will decide row-buffering strategy, and init
+ * the RowBuffers where required.
+ */
+Uint32
+Dbspj::initRowBuffers(Ptr<Request> requestPtr)
+{
+  Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
+
+  /**
+   * Init ROW_BUFFERS iff Request has to buffer any rows.
+   */
+  if (requestPtr.p->m_bits & Request::RT_ROW_BUFFERS)
+  {
+    jam();
 
     /**
      * Iff, multi-scan is non-bushy (normal case)
-     *   we don't strictly need RT_VAR_ALLOC for RT_ROW_BUFFERS
+     *   we don't strictly need BUFFER_VAR for RT_ROW_BUFFERS
      *   but could instead pop-row stack frame,
      *     however this is not implemented...
      *
-     * so, use RT_VAR_ALLOC
+     * so, currently use BUFFER_VAR if 'RT_MULTI_SCAN'
+     *
+     * NOTE: This should easily be solvable by having a 
+     *       RowBuffer for each TreeNode instead
      */
-    if (requestPtr.p->m_bits & Request::RT_ROW_BUFFERS)
-    {
-      jam();
-      requestPtr.p->m_bits |= Request::RT_VAR_ALLOC;
+    if (requestPtr.p->m_bits & Request::RT_MULTI_SCAN)
+    {
+      jam();
+      requestPtr.p->m_rowBuffer.init(BUFFER_VAR);
+    }
+    else
+    {
+      jam();
+      requestPtr.p->m_rowBuffer.init(BUFFER_STACK);
+    }
+
+    Ptr<TreeNode> treeNodePtr;
+    for (list.first(treeNodePtr); !treeNodePtr.isNull(); list.next(treeNodePtr))
+    {
+      jam();
+      ndbassert(treeNodePtr.p->m_batch_size > 0);
+      /**
+       * Construct a List or Map RowCollection for those TreeNodes
+       * requiring rows to be buffered.
+       */
+      if (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER_MAP)
+      {
+        jam();
+        treeNodePtr.p->m_rows.construct (RowCollection::COLLECTION_MAP,
+                                         requestPtr.p->m_rowBuffer,
+                                         treeNodePtr.p->m_batch_size);
+      }
+      else if (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER)
+      {
+        jam();
+        treeNodePtr.p->m_rows.construct (RowCollection::COLLECTION_LIST,
+                                         requestPtr.p->m_rowBuffer,
+                                         treeNodePtr.p->m_batch_size);
+      }
     }
   }
 
   return 0;
-
-error:
-  jam();
-  return err;
 }
 
 Uint32
@@ -1859,64 +1894,46 @@
      << ", request: " << requestPtr.i
   );
 
-  // only when var-alloc, or else stack will be popped wo/ consideration
-  // to individual rows
-  ndbassert(requestPtr.p->m_bits & Request::RT_VAR_ALLOC);
   ndbassert(treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER);
 
-  /**
-   * Two ways to iterate...
-   */
-  if ((treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER_MAP) == 0)
+  Uint32 cnt = 0;
+  RowIterator iter;
+  for (first(treeNodePtr.p->m_rows, iter); !iter.isNull(); )
   {
     jam();
-    Uint32 cnt = 0;
-    SLFifoRowListIterator iter;
-    for (first(requestPtr, treeNodePtr, iter); !iter.isNull(); )
-    {
-      jam();
-      RowRef pos = iter.m_ref;
-      next(iter);
-      releaseRow(requestPtr, pos);
-      cnt ++;
-    }
-    treeNodePtr.p->m_row_list.init();
-    DEBUG("SLFifoRowListIterator: released " << cnt << " rows!");
+    RowRef pos = iter.m_base.m_ref;
+    next(iter);
+    releaseRow(treeNodePtr.p->m_rows, pos);
+    cnt ++;
   }
-  else
+  treeNodePtr.p->m_rows.init();
+  DEBUG("RowIterator: released " << cnt << " rows!");
+
+  if (treeNodePtr.p->m_rows.m_type == RowCollection::COLLECTION_MAP)
   {
     jam();
-    Uint32 cnt = 0;
-    RowMapIterator iter;
-    for (first(requestPtr, treeNodePtr, iter); !iter.isNull(); )
-    {
-      jam();
-      RowRef pos = iter.m_ref;
-      // this could be made more efficient by not actually seting up m_row_ptr
-      next(iter);
-      releaseRow(requestPtr, pos);
-      cnt++;
-    }
-
     // Release the (now empty) RowMap
-    RowMap& map = treeNodePtr.p->m_row_map;
+    RowMap& map = treeNodePtr.p->m_rows.m_map;
     if (!map.isNull())
     {
       jam();
       RowRef ref;
       map.copyto(ref);
-      releaseRow(requestPtr, ref);  // Map was allocated in row memory
-      map.init();
+      releaseRow(treeNodePtr.p->m_rows, ref);  // Map was allocated in row memory
     }
-    DEBUG("RowMapIterator: released " << cnt << " rows!");
   }
 }
 
 void
-Dbspj::releaseRow(Ptr<Request> requestPtr, RowRef pos)
+Dbspj::releaseRow(RowCollection& collection, RowRef pos)
 {
-  ndbassert(requestPtr.p->m_bits & Request::RT_VAR_ALLOC);
-  ndbassert(pos.m_allocator == 1);
+  // only when var-alloc, or else stack will be popped wo/ consideration
+  // to individual rows
+  ndbassert(collection.m_base.m_rowBuffer != NULL);
+  ndbassert(collection.m_base.m_rowBuffer->m_type == BUFFER_VAR);
+  ndbassert(pos.m_alloc_type == BUFFER_VAR);
+
+  RowBuffer& rowBuffer = *collection.m_base.m_rowBuffer;
   Ptr<RowPage> ptr;
   m_page_pool.getPtr(ptr, pos.m_page_id);
   ((Var_page*)ptr.p)->free_record(pos.m_page_pos, Var_page::CHAIN);
@@ -1925,7 +1942,7 @@
   {
     jam();
     LocalDLFifoList<RowPage> list(m_page_pool,
-                                  requestPtr.p->m_rowBuffer.m_page_list);
+                                  rowBuffer.m_page_list);
     const bool last = list.hasNext(ptr) == false;
     list.remove(ptr);
     if (list.isEmpty())
@@ -1935,7 +1952,7 @@
        * Don't remove last page...
        */
       list.addLast(ptr);
-      requestPtr.p->m_rowBuffer.m_var.m_free = free_space;
+      rowBuffer.m_var.m_free = free_space;
     }
     else
     {
@@ -1948,20 +1965,19 @@
          */
         Ptr<RowPage> newLastPtr;
         ndbrequire(list.last(newLastPtr));
-        requestPtr.p->m_rowBuffer.m_var.m_free =
-          ((Var_page*)newLastPtr.p)->free_space;
+        rowBuffer.m_var.m_free = ((Var_page*)newLastPtr.p)->free_space;
       }
       releasePage(ptr);
     }
   }
-  else if (free_space > requestPtr.p->m_rowBuffer.m_var.m_free)
+  else if (free_space > rowBuffer.m_var.m_free)
   {
     jam();
     LocalDLFifoList<RowPage> list(m_page_pool,
-                                  requestPtr.p->m_rowBuffer.m_page_list);
+                                  rowBuffer.m_page_list);
     list.remove(ptr);
     list.addLast(ptr);
-    requestPtr.p->m_rowBuffer.m_var.m_free = free_space;
+    rowBuffer.m_var.m_free = free_space;
   }
 }
 
@@ -1988,7 +2004,7 @@
         list.remove();
       }
     }
-    requestPtr.p->m_rowBuffer.stack_init();
+    requestPtr.p->m_rowBuffer.reset();
   }
 
   if (reset)
@@ -1998,19 +2014,7 @@
     for (list.first(nodePtr); !nodePtr.isNull(); list.next(nodePtr))
     {
       jam();
-      if (nodePtr.p->m_bits & TreeNode::T_ROW_BUFFER)
-      {
-        jam();
-        if (nodePtr.p->m_bits & TreeNode::T_ROW_BUFFER_MAP)
-        {
-          jam();
-          nodePtr.p->m_row_map.init();
-        }
-        else
-        {
-          nodePtr.p->m_row_list.init();
-        }
-      }
+      nodePtr.p->m_rows.init();
     }
   }
 }
@@ -2569,6 +2573,11 @@
   {
     jam();
     Uint32 err;
+
+    DEBUG("Need to storeRow"
+      << ", node: " << treeNodePtr.p->m_node_no
+    );
+
     if (ERROR_INSERTED(17120) ||
        (ERROR_INSERTED(17121) && treeNodePtr.p->m_parentPtrI != RNIL))
     {
@@ -2576,7 +2585,7 @@
       CLEAR_ERROR_INSERT_VALUE;
       abort(signal, requestPtr, DbspjErr::OutOfRowMemory);
     }
-    else if ((err = storeRow(requestPtr, treeNodePtr, row)) != 0)
+    else if ((err = storeRow(treeNodePtr.p->m_rows, row)) != 0)
     {
       jam();
       abort(signal, requestPtr, err);
@@ -2593,60 +2602,43 @@
 }
 
 Uint32
-Dbspj::storeRow(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr, RowPtr &row)
+Dbspj::storeRow(RowCollection& collection, RowPtr &row)
 {
   ndbassert(row.m_type == RowPtr::RT_SECTION);
   SegmentedSectionPtr dataPtr = row.m_row_data.m_section.m_dataPtr;
   Uint32 * headptr = (Uint32*)row.m_row_data.m_section.m_header;
   Uint32 headlen = 1 + row.m_row_data.m_section.m_header->m_len;
 
-  DEBUG("storeRow"
-     << ", node: " << treeNodePtr.p->m_node_no
-     << ", request: " << requestPtr.i
-  );
-
   /**
-   * If rows are not in map, then they are kept in linked list
+   * Rows might be stored at an offset within the collection.
    */
-  Uint32 linklen = (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER_MAP)?
-    0 : 2;
+  const Uint32 offset = collection.rowOffset();
 
   Uint32 totlen = 0;
   totlen += dataPtr.sz;
   totlen += headlen;
-  totlen += linklen;
+  totlen += offset;
 
   RowRef ref;
-  Uint32 * dstptr = 0;
-  if ((requestPtr.p->m_bits & Request::RT_VAR_ALLOC) == 0)
-  {
-    jam();
-    dstptr = stackAlloc(requestPtr.p->m_rowBuffer, ref, totlen);
-  }
-  else
-  {
-    jam();
-    dstptr = varAlloc(requestPtr.p->m_rowBuffer, ref, totlen);
-  }
-
+  Uint32* const dstptr = rowAlloc(*collection.m_base.m_rowBuffer, ref, totlen);
   if (unlikely(dstptr == 0))
   {
     jam();
     return DbspjErr::OutOfRowMemory;
   }
-  memcpy(dstptr + linklen, headptr, 4 * headlen);
-  copy(dstptr + linklen + headlen, dataPtr);
+  memcpy(dstptr + offset, headptr, 4 * headlen);
+  copy(dstptr + offset + headlen, dataPtr);
 
-  if (linklen)
+  if (collection.m_type == RowCollection::COLLECTION_LIST)
   {
     jam();
     NullRowRef.copyto_link(dstptr); // Null terminate list...
-    add_to_list(treeNodePtr.p->m_row_list, ref);
+    add_to_list(collection.m_list, ref);
   }
   else
   {
     jam();
-    Uint32 error = add_to_map(requestPtr, treeNodePtr, row.m_src_correlation, ref);
+    Uint32 error = add_to_map(collection.m_map, row.m_src_correlation, ref);
     if (unlikely(error))
       return error;
   }
@@ -2656,30 +2648,17 @@
    * as above add_to_xxx may mave reorganized memory causing
    * alloced row to be moved.
    */
-  Uint32 * rowptr = 0;
-  if (ref.m_allocator == 0)
-  {
-    jam();
-    rowptr = get_row_ptr_stack(ref);
-  }
-  else
-  {
-    jam();
-    rowptr = get_row_ptr_var(ref);
-  }
-
-//ndbrequire(rowptr==dstptr);  // It moved which we now do handle
-  setupRowPtr(treeNodePtr, row, ref, rowptr);
+  const Uint32* const rowptr = get_row_ptr(ref);
+  setupRowPtr(collection, row, ref, rowptr);
   return 0;
 }
 
 void
-Dbspj::setupRowPtr(Ptr<TreeNode> treeNodePtr,
+Dbspj::setupRowPtr(const RowCollection& collection,
                    RowPtr& row, RowRef ref, const Uint32 * src)
 {
-  Uint32 linklen = (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER_MAP)?
-    0 : 2;
-  const RowPtr::Header * headptr = (RowPtr::Header*)(src + linklen);
+  const Uint32 offset = collection.rowOffset();
+  const RowPtr::Header * headptr = (RowPtr::Header*)(src + offset);
   Uint32 headlen = 1 + headptr->m_len;
 
   row.m_type = RowPtr::RT_LINEAR;
@@ -2704,20 +2683,10 @@
      * add last to list
      */
     RowRef last;
-    last.m_allocator = rowref.m_allocator;
+    last.m_alloc_type = rowref.m_alloc_type;
     last.m_page_id = list.m_last_row_page_id;
     last.m_page_pos = list.m_last_row_page_pos;
-    Uint32 * rowptr;
-    if (rowref.m_allocator == 0)
-    {
-      jam();
-      rowptr = get_row_ptr_stack(last);
-    }
-    else
-    {
-      jam();
-      rowptr = get_row_ptr_var(last);
-    }
+    Uint32 * const rowptr = get_row_ptr(last);
     rowref.copyto_link(rowptr);
   }
 
@@ -2726,29 +2695,28 @@
 }
 
 Uint32 *
-Dbspj::get_row_ptr_stack(RowRef pos)
-{
-  ndbassert(pos.m_allocator == 0);
-  Ptr<RowPage> ptr;
-  m_page_pool.getPtr(ptr, pos.m_page_id);
-  return ptr.p->m_data + pos.m_page_pos;
-}
-
-Uint32 *
-Dbspj::get_row_ptr_var(RowRef pos)
-{
-  ndbassert(pos.m_allocator == 1);
-  Ptr<RowPage> ptr;
-  m_page_pool.getPtr(ptr, pos.m_page_id);
-  return ((Var_page*)ptr.p)->get_ptr(pos.m_page_pos);
-}
-
+Dbspj::get_row_ptr(RowRef pos)
+{
+  Ptr<RowPage> ptr;
+  m_page_pool.getPtr(ptr, pos.m_page_id);
+  if (pos.m_alloc_type == BUFFER_STACK) // ::stackAlloc() memory
+  {
+    jam();
+    return ptr.p->m_data + pos.m_page_pos;
+  }
+  else                                 // ::varAlloc() memory
+  {
+    jam();
+    ndbassert(pos.m_alloc_type == BUFFER_VAR);
+    return ((Var_page*)ptr.p)->get_ptr(pos.m_page_pos);
+  }
+}
+
+inline
 bool
-Dbspj::first(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr,
+Dbspj::first(const SLFifoRowList& list,
              SLFifoRowListIterator& iter)
 {
-  Uint32 var = (requestPtr.p->m_bits & Request::RT_VAR_ALLOC) != 0;
-  SLFifoRowList & list = treeNodePtr.p->m_row_list;
   if (list.isNull())
   {
     jam();
@@ -2756,23 +2724,15 @@
     return false;
   }
 
-  iter.m_ref.m_allocator = var;
+  //  const Buffer_type allocator = list.m_rowBuffer->m_type;
+  iter.m_ref.m_alloc_type = list.m_rowBuffer->m_type;
   iter.m_ref.m_page_id = list.m_first_row_page_id;
   iter.m_ref.m_page_pos = list.m_first_row_page_pos;
-  if (var == 0)
-  {
-    jam();
-    iter.m_row_ptr = get_row_ptr_stack(iter.m_ref);
-  }
-  else
-  {
-    jam();
-    iter.m_row_ptr = get_row_ptr_var(iter.m_ref);
-  }
-
+  iter.m_row_ptr = get_row_ptr(iter.m_ref);
   return true;
 }
 
+inline
 bool
 Dbspj::next(SLFifoRowListIterator& iter)
 {
@@ -2782,63 +2742,25 @@
     jam();
     return false;
   }
-
-  if (iter.m_ref.m_allocator == 0)
-  {
-    jam();
-    iter.m_row_ptr = get_row_ptr_stack(iter.m_ref);
-  }
-  else
-  {
-    jam();
-    iter.m_row_ptr = get_row_ptr_var(iter.m_ref);
-  }
+  iter.m_row_ptr = get_row_ptr(iter.m_ref);
   return true;
 }
 
-bool
-Dbspj::next(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr,
-            SLFifoRowListIterator& iter, SLFifoRowListIteratorPtr start)
-{
-  Uint32 var = (requestPtr.p->m_bits & Request::RT_VAR_ALLOC) != 0;
-  (void)var;
-  ndbassert(var == iter.m_ref.m_allocator);
-  if (iter.m_ref.m_allocator == 0)
-  {
-    jam();
-    iter.m_row_ptr = get_row_ptr_stack(start.m_ref);
-  }
-  else
-  {
-    jam();
-    iter.m_row_ptr = get_row_ptr_var(start.m_ref);
-  }
-  return next(iter);
-}
-
 Uint32
-Dbspj::add_to_map(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr,
+Dbspj::add_to_map(RowMap& map,
                   Uint32 corrVal, RowRef rowref)
 {
   Uint32 * mapptr;
-  RowMap& map = treeNodePtr.p->m_row_map;
   if (map.isNull())
   {
     jam();
-    Uint16 batchsize = treeNodePtr.p->m_batch_size;
-    Uint32 sz16 = RowMap::MAP_SIZE_PER_REF_16 * batchsize;
+    ndbassert(map.m_size > 0);
+    ndbassert(map.m_rowBuffer != NULL);
+
+    Uint32 sz16 = RowMap::MAP_SIZE_PER_REF_16 * map.m_size;
     Uint32 sz32 = (sz16 + 1) / 2;
     RowRef ref;
-    if ((requestPtr.p->m_bits & Request::RT_VAR_ALLOC) == 0)
-    {
-      jam();
-      mapptr = stackAlloc(requestPtr.p->m_rowBuffer, ref, sz32);
-    }
-    else
-    {
-      jam();
-      mapptr = varAlloc(requestPtr.p->m_rowBuffer, ref, sz32);
-    }
+    mapptr = rowAlloc(*map.m_rowBuffer, ref, sz32);
     if (unlikely(mapptr == 0))
     {
       jam();
@@ -2846,7 +2768,6 @@
     }
     map.assign(ref);
     map.m_elements = 0;
-    map.m_size = batchsize;
     map.clear(mapptr);
   }
   else
@@ -2854,16 +2775,7 @@
     jam();
     RowRef ref;
     map.copyto(ref);
-    if (ref.m_allocator == 0)
-    {
-      jam();
-      mapptr = get_row_ptr_stack(ref);
-    }
-    else
-    {
-      jam();
-      mapptr = get_row_ptr_var(ref);
-    }
+    mapptr = get_row_ptr(ref);
   }
 
   Uint32 pos = corrVal & 0xFFFF;
@@ -2885,12 +2797,11 @@
   return 0;
 }
 
+inline
 bool
-Dbspj::first(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr,
+Dbspj::first(const RowMap& map,
              RowMapIterator & iter)
 {
-  Uint32 var = (requestPtr.p->m_bits & Request::RT_VAR_ALLOC) != 0;
-  RowMap& map = treeNodePtr.p->m_row_map;
   if (map.isNull())
   {
     jam();
@@ -2898,18 +2809,9 @@
     return false;
   }
 
-  if (var == 0)
-  {
-    jam();
-    iter.m_map_ptr = get_row_ptr_stack(map.m_map_ref);
-  }
-  else
-  {
-    jam();
-    iter.m_map_ptr = get_row_ptr_var(map.m_map_ref);
-  }
+  iter.m_map_ptr = get_row_ptr(map.m_map_ref);
   iter.m_size = map.m_size;
-  iter.m_ref.m_allocator = var;
+  iter.m_ref.m_alloc_type = map.m_rowBuffer->m_type;
 
   Uint32 pos = 0;
   while (RowMap::isNull(iter.m_map_ptr, pos) && pos < iter.m_size)
@@ -2926,20 +2828,12 @@
     jam();
     RowMap::load(iter.m_map_ptr, pos, iter.m_ref);
     iter.m_element_no = pos;
-    if (var == 0)
-    {
-      jam();
-      iter.m_row_ptr = get_row_ptr_stack(iter.m_ref);
-    }
-    else
-    {
-      jam();
-      iter.m_row_ptr = get_row_ptr_var(iter.m_ref);
-    }
+    iter.m_row_ptr = get_row_ptr(iter.m_ref);
     return true;
   }
 }
 
+inline
 bool
 Dbspj::next(RowMapIterator & iter)
 {
@@ -2958,45 +2852,46 @@
     jam();
     RowMap::load(iter.m_map_ptr, pos, iter.m_ref);
     iter.m_element_no = pos;
-    if (iter.m_ref.m_allocator == 0)
-    {
-      jam();
-      iter.m_row_ptr = get_row_ptr_stack(iter.m_ref);
-    }
-    else
-    {
-      jam();
-      iter.m_row_ptr = get_row_ptr_var(iter.m_ref);
-    }
+    iter.m_row_ptr = get_row_ptr(iter.m_ref);
     return true;
   }
 }
 
 bool
-Dbspj::next(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr,
-            RowMapIterator & iter, RowMapIteratorPtr start)
-{
-  Uint32 var = (requestPtr.p->m_bits & Request::RT_VAR_ALLOC) != 0;
-  RowMap& map = treeNodePtr.p->m_row_map;
-  ndbrequire(!map.isNull());
-
-  if (var == 0)
-  {
-    jam();
-    iter.m_map_ptr = get_row_ptr_stack(map.m_map_ref);
-  }
-  else
-  {
-    jam();
-    iter.m_map_ptr = get_row_ptr_var(map.m_map_ref);
-  }
-  iter.m_size = map.m_size;
-
-  RowMap::load(iter.m_map_ptr, start.m_element_no, iter.m_ref);
-  iter.m_element_no = start.m_element_no;
-  return next(iter);
-}
-
+Dbspj::first(const RowCollection& collection,
+             RowIterator& iter)
+{
+  iter.m_type = collection.m_type;
+  if (iter.m_type == RowCollection::COLLECTION_LIST)
+  {
+    jam();
+    return first(collection.m_list, iter.m_list);
+  }
+  else
+  {
+    jam();
+    ndbassert(iter.m_type == RowCollection::COLLECTION_MAP);
+    return first(collection.m_map, iter.m_map);
+  }
+}
+
+bool
+Dbspj::next(RowIterator& iter)
+{
+  if (iter.m_type == RowCollection::COLLECTION_LIST)
+  {
+    jam();
+    return next(iter.m_list);
+  }
+  else
+  {
+    jam();
+    ndbassert(iter.m_type == RowCollection::COLLECTION_MAP);
+    return next(iter.m_map);
+  }
+}
+
+inline
 Uint32 *
 Dbspj::stackAlloc(RowBuffer & buffer, RowRef& dst, Uint32 sz)
 {
@@ -3025,11 +2920,12 @@
 
   dst.m_page_id = ptr.i;
   dst.m_page_pos = pos;
-  dst.m_allocator = 0;
+  dst.m_alloc_type = BUFFER_STACK;
   buffer.m_stack.m_pos = pos + sz;
   return ptr.p->m_data + pos;
 }
 
+inline
 Uint32 *
 Dbspj::varAlloc(RowBuffer & buffer, RowRef& dst, Uint32 sz)
 {
@@ -3061,11 +2957,32 @@
 
   dst.m_page_id = ptr.i;
   dst.m_page_pos = pos;
-  dst.m_allocator = 1;
+  dst.m_alloc_type = BUFFER_VAR;
   buffer.m_var.m_free = vp->free_space;
   return vp->get_ptr(pos);
 }
 
+Uint32 *
+Dbspj::rowAlloc(RowBuffer& rowBuffer, RowRef& dst, Uint32 sz)
+{
+  if (rowBuffer.m_type == BUFFER_STACK)
+  {
+    jam();
+    return stackAlloc(rowBuffer, dst, sz);
+  }
+  else if (rowBuffer.m_type == BUFFER_VAR)
+  {
+    jam();
+    return varAlloc(rowBuffer, dst, sz);
+  }
+  else
+  {
+    jam();
+    ndbrequire(false);
+    return NULL;
+  }
+}
+
 bool
 Dbspj::allocPage(Ptr<RowPage> & ptr)
 {
@@ -7523,49 +7440,28 @@
     m_treenode_pool.getPtr(treeNodePtr, treeNodePtr.p->m_parentPtrI);
     DEBUG("appendFromParent"
        << ", node: " << treeNodePtr.p->m_node_no);
-    if (unlikely((treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER_MAP) == 0))
+    if (unlikely(treeNodePtr.p->m_rows.m_type != RowCollection::COLLECTION_MAP))
     {
       DEBUG_CRASH();
       return DbspjErr::InvalidPattern;
     }
 
     RowRef ref;
-    treeNodePtr.p->m_row_map.copyto(ref);
-    Uint32 allocator = ref.m_allocator;
-    const Uint32 * mapptr;
-    if (allocator == 0)
-    {
-      jam();
-      mapptr = get_row_ptr_stack(ref);
-    }
-    else
-    {
-      jam();
-      mapptr = get_row_ptr_var(ref);
-    }
+    treeNodePtr.p->m_rows.m_map.copyto(ref);
+    const Uint32* const mapptr = get_row_ptr(ref);
 
     Uint32 pos = corrVal >> 16; // parent corr-val
-    if (unlikely(! (pos < treeNodePtr.p->m_row_map.m_size)))
+    if (unlikely(! (pos < treeNodePtr.p->m_rows.m_map.m_size)))
     {
       DEBUG_CRASH();
       return DbspjErr::InvalidPattern;
     }
 
     // load ref to parent row
-    treeNodePtr.p->m_row_map.load(mapptr, pos, ref);
+    treeNodePtr.p->m_rows.m_map.load(mapptr, pos, ref);
 
-    const Uint32 * rowptr;
-    if (allocator == 0)
-    {
-      jam();
-      rowptr = get_row_ptr_stack(ref);
-    }
-    else
-    {
-      jam();
-      rowptr = get_row_ptr_var(ref);
-    }
-    setupRowPtr(treeNodePtr, targetRow, ref, rowptr);
+    const Uint32* const rowptr = get_row_ptr(ref);
+    setupRowPtr(treeNodePtr.p->m_rows, targetRow, ref, rowptr);
 
     if (levels)
     {

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.1 branch (ole.john.aske:4653 to 4654) Ole John Aske9 Nov