List:Commits« Previous MessageNext Message »
From:Ole John Aske Date:August 16 2011 1:37pm
Subject:bzr push into mysql-5.1-telco-7.0 branch (ole.john.aske:4456 to 4457)
View as plain text  
 4457 Ole John Aske	2011-08-16
      SPJ Refactoring of how the 'remainingSubScans nodemask' is administrated 
      in the NdbRootFragment / NdbResultStream[] objects:
      
      Instead of ::setSubScanCompletion() on each NdbResultStream from
      execSCAN_TABCONF(), we set ::setRemainingSubScans() with the
      entire nodeMask on the NdbRootFragment. The individual subScan 
      completion status is then later extracted for each NdbResultStream
      when required.
        
      This result in simplification of logic and reduce LOC used to implement
      'remaining subscans' logic by 30-40%.

    modified:
      storage/ndb/src/ndbapi/NdbQueryOperation.cpp
 4456 Ole John Aske	2011-08-16
      SPJ: Refactoring of how & when the parent/child row correlation is handled:
      
      Previously the correlation id's was decoded, and the parent/child 
      hashMaps built as part of execTRANSID_AI().
      
      This work is now deferred until a complete batch of result rows has been
      received - and at this point it is handled by the thread which was waiting
      for the result batch instead of the receiver thread.
      
      Note: This patch is also a step in the direction of moving building
      of the correlation hashmap entirely outside transporter mutex protected
      code.

    modified:
      storage/ndb/src/ndbapi/NdbQueryOperation.cpp
=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2011-08-16 13:20:11 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2011-08-16 13:37:24 +0000
@@ -247,6 +247,16 @@ public:
    */
   bool isEmpty() const;
 
+  /** 
+   * This method is used for marking which streams belonging to this
+   * NdbRootFragment which has remaining batches for a sub scan
+   * instantiated from the current batch of its parent operation.
+   */
+  void setRemainingSubScans(Uint32 nodeMask)
+  { 
+    m_remainingScans = nodeMask;
+  }
+
   /** Release resources after last row has been returned */
   void postFetchRelease();
 
@@ -280,6 +290,12 @@ private:
    * TCKEYCONF message has been received */
   bool m_confReceived;
 
+  /**
+   * A bitmask of operation id's for which we will receive more
+   * ResultSets in a NEXTREQ.
+   */
+  Uint32 m_remainingScans;
+
   /** 
    * Used for implementing a hash map from root receiver ids to a 
    * NdbRootFragment instance. m_idMapHead is the index of the first
@@ -353,7 +369,7 @@ public:
    * Update whatever required before the appl. are allowed to navigate the result.
    * @return true if node and all its siblings have returned all rows.
    */ 
-  bool prepareResultSet();
+  bool prepareResultSet(Uint32 remainingScans);
 
   /**
    * Navigate within the current result batch to resp. first and next row.
@@ -373,29 +389,23 @@ public:
   { return m_iterState == Iter_finished; }
 
   /** 
-   * This method is
-   * used for marking a stream as holding the last batch of a sub scan. 
-   * This means that it is the last batch of the scan that was instantiated 
-   * from the current batch of its parent operation.
-   */
-  void setSubScanCompletion(bool complete)
-  { 
-    // Lookups should always be 'complete'
-    assert(complete || isScanResult());
-    m_subScanComplete = complete; 
-  }
-
-  /** 
    * This method 
-   * returns true if this result stream holds the last batch of a sub scan
+   * returns true if this result stream holds the last batch of a sub scan.
    * This means that it is the last batch of the scan that was instantiated 
    * from the current batch of its parent operation.
    */
-  bool isSubScanComplete() const
+  bool isSubScanComplete(Uint32 remainingScans) const
   { 
-    // Lookups should always be 'complete'
-    assert(m_subScanComplete || isScanResult());
-    return m_subScanComplete; 
+    /**
+     * Find the node number seen by the SPJ block. Since a unique index
+     * operation will have two distincts nodes in the tree used by the
+     * SPJ block, this number may be different from 'opNo'.
+     */
+    const Uint32 internalOpNo = m_operation.getQueryOperationDef().getQueryOperationId();
+
+    const bool complete = !((remainingScans >> internalOpNo) & 1);
+    assert(complete || isScanResult());    // Lookups should always be 'complete'
+    return complete; 
   }
 
   bool isScanQuery() const
@@ -508,14 +518,6 @@ private:
    */
   Uint16 m_currentRow;
   
-  /** 
-   * This field is only used for result streams of scan operations. If set,
-   * it indicates that the stream is holding the last batch of a sub scan. 
-   * This means that it is the last batch of the scan that was instantiated 
-   * from the current batch of its parent operation.
-   */
-  bool m_subScanComplete;
-
   /** Max #rows which this stream may recieve in its TupleSet structures */
   Uint32 m_maxRows;
 
@@ -611,7 +613,6 @@ NdbResultStream::NdbResultStream(NdbQuer
   m_rowCount(0),
   m_iterState(Iter_notStarted),
   m_currentRow(tupleNotFound),
-  m_subScanComplete(true),
   m_maxRows(0),
   m_tupleSet(NULL)
 {};
@@ -827,10 +828,10 @@ NdbResultStream::execTRANSID_AI(const Ui
  *    rows.
  */
 bool 
-NdbResultStream::prepareResultSet()
+NdbResultStream::prepareResultSet(Uint32 remainingScans)
 {
-  bool isComplete = isSubScanComplete();  //Childs with more rows
-  assert(isComplete || isScanResult());   //Lookups always 'complete'
+  bool isComplete = isSubScanComplete(remainingScans); //Childs with more rows
+  assert(isComplete || isScanResult());                //Lookups always 'complete'
 
   // Set correct #rows received in the NdbReceiver.
   getReceiver().m_result_rows = getRowCount();
@@ -866,7 +867,7 @@ NdbResultStream::prepareResultSet()
   {
     const NdbQueryOperationImpl& child = m_operation.getChildOperation(childNo);
     NdbResultStream& childStream = m_rootFrag.getResultStream(child);
-    const bool allSubScansComplete = childStream.prepareResultSet();
+    const bool allSubScansComplete = childStream.prepareResultSet(remainingScans);
 
     Uint32 childId = child.getQueryOperationDef().getQueryOperationIx();
 
@@ -1035,6 +1036,7 @@ NdbRootFragment::NdbRootFragment():
   m_resultStreams(NULL),
   m_outstandingResults(0),
   m_confReceived(false),
+  m_remainingScans(0),
   m_idMapHead(-1),
   m_idMapNext(-1)
 {
@@ -1097,13 +1099,25 @@ void NdbRootFragment::reset()
   assert(m_fragNo!=voidFragNo);
   assert(m_outstandingResults == 0);
   assert(m_confReceived);
+
+  for (unsigned opNo=0; opNo<m_query->getNoOfOperations(); opNo++) 
+  {
+    if (!m_resultStreams[opNo].isSubScanComplete(m_remainingScans))
+    {
+      /**
+       * Reset m_resultStreams[] and all its descendants, since all these
+       * streams will get a new set of rows in the next batch.
+       */ 
+      m_resultStreams[opNo].reset();
+    }
+  }
   m_confReceived = false;
 }
 
 void NdbRootFragment::prepareResultSet()
 {
   NdbResultStream& rootStream = getResultStream(0);
-  rootStream.prepareResultSet();  
+  rootStream.prepareResultSet(m_remainingScans);  
 
   /* Position at the first (sorted?) row available from this fragments.
    */
@@ -3004,21 +3018,6 @@ NdbQueryImpl::sendFetchMore(NdbRootFragm
 
   emptyFrag.reset();
 
-  for (unsigned opNo=0; opNo<m_countOperations; opNo++) 
-  {
-    NdbResultStream& resultStream = 
-       emptyFrag.getResultStream(opNo);
-
-    if (!resultStream.isSubScanComplete())
-    {
-      /**
-       * Reset resultstream and all its descendants, since all these
-       * streams will get a new set of rows in the next batch.
-       */ 
-      resultStream.reset();
-    }
-  }
-
   Ndb& ndb = *getNdbTransaction().getNdb();
   NdbApiSignal tSignal(&ndb);
   tSignal.setSignal(GSN_SCAN_NEXTREQ, refToBlock(m_scanTransaction->m_tcRef));
@@ -4798,6 +4797,7 @@ NdbQueryOperationImpl::execSCAN_TABCONF(
     return false;
   }
   rootFrag->setConfReceived();
+  rootFrag->setRemainingSubScans(nodeMask);
   rootFrag->incrOutstandingResults(rowCount);
 
   // Handle for SCAN_NEXTREQ, RNIL -> EOF
@@ -4810,31 +4810,6 @@ NdbQueryOperationImpl::execSCAN_TABCONF(
            << endl;
   }
 
-  const NdbQueryDefImpl& queryDef = m_queryImpl.getQueryDef();
-  /* Mark each scan node to indicate if the current batch is the last in the
-   * current sub-scan or not.
-   */
-  for (Uint32 opNo = 0; opNo < queryDef.getNoOfOperations(); opNo++)
-  {
-    const NdbQueryOperationImpl& op = m_queryImpl.getQueryOperation(opNo);
-    /**
-     * Find the node number seen by the SPJ block. Since a unique index
-     * operation will have two distincts nodes in the tree used by the
-     * SPJ block, this number may be different from 'opNo'.
-     */
-    const Uint32 internalOpNo = op.getQueryOperationDef().getQueryOperationId();
-    assert(internalOpNo >= opNo);
-    const bool complete = ((nodeMask >> internalOpNo) & 1) == 0;
-
-    // Lookups should always be 'complete'
-    assert(complete ||  op.getQueryOperationDef().isScanOperation());
-    rootFrag->getResultStream(opNo).setSubScanCompletion(complete);
-  }
-  // Check that nodeMask does not have more bits than we have operations. 
-  assert(nodeMask >> 
-         (1+queryDef.getQueryOperation(queryDef.getNoOfOperations() - 1)
-          .getQueryOperationId()) == 0);
-
   bool ret = false;
   if (rootFrag->isFragBatchComplete())
   {

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.0 branch (ole.john.aske:4456 to 4457) Ole John Aske17 Aug