From 106d203f25e6f13cfdbb26c270572311e843d2c5 Mon Sep 17 00:00:00 2001
From: "joreland@mysql.com" <>
Date: Sat, 25 Sep 2004 10:16:37 +0200
Subject: [PATCH] Fix memory leak

---
 ndb/include/ndb_global.h            |   1 +
 ndb/src/common/util/ndb_init.c      |   6 +
 ndb/src/ndbapi/NdbScanOperation.cpp |   9 +-
 ndb/src/ndbapi/NdbScanReceiver.cpp  | 187 -------------------------
 ndb/src/ndbapi/NdbScanReceiver.hpp  | 210 ----------------------------
 ndb/src/ndbapi/Ndbinit.cpp          |   8 +-
 6 files changed, 19 insertions(+), 402 deletions(-)
 delete mode 100644 ndb/src/ndbapi/NdbScanReceiver.cpp
 delete mode 100644 ndb/src/ndbapi/NdbScanReceiver.hpp

diff --git a/ndb/include/ndb_global.h b/ndb/include/ndb_global.h
index 19bd387c457..3ce37a2edee 100644
--- a/ndb/include/ndb_global.h
+++ b/ndb/include/ndb_global.h
@@ -78,6 +78,7 @@ extern "C" {
 
 /* call in main() - does not return on error */
 extern int ndb_init(void);
+extern void ndb_end(int);
 
 #ifndef HAVE_STRDUP
 extern char * strdup(const char *s);
diff --git a/ndb/src/common/util/ndb_init.c b/ndb/src/common/util/ndb_init.c
index b160ed3636b..f3aa734d7f9 100644
--- a/ndb/src/common/util/ndb_init.c
+++ b/ndb/src/common/util/ndb_init.c
@@ -27,3 +27,9 @@ ndb_init()
   }
   return 0;
 }
+
+void
+ndb_end(int flags)
+{
+  my_end(flags);
+}
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index ac5f4268386..8db4778f2b9 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -52,6 +52,7 @@ NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
 NdbScanOperation::~NdbScanOperation()
 {
   for(Uint32 i = 0; i<m_allocated_receivers; i++){
+    m_receivers[i]->release();
     theNdb->releaseNdbScanRec(m_receivers[i]);
   }
   delete[] m_array;
@@ -191,7 +192,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
     return 0;
   }
   
-  theSCAN_TABREQ = theNdb->getSignal();
+  theSCAN_TABREQ = (!theSCAN_TABREQ ? theNdb->getSignal() : theSCAN_TABREQ);
   if (theSCAN_TABREQ == NULL) {
     setErrorCodeAbort(4000);
     return 0;
@@ -719,6 +720,12 @@ void NdbScanOperation::release()
   for(Uint32 i = 0; i<m_allocated_receivers; i++){
     m_receivers[i]->release();
   }
+  if(theSCAN_TABREQ)
+  {
+    theNdb->releaseSignal(theSCAN_TABREQ);
+    theSCAN_TABREQ = 0;
+  }
+  NdbOperation::release();
 }
 
 /***************************************************************************
diff --git a/ndb/src/ndbapi/NdbScanReceiver.cpp b/ndb/src/ndbapi/NdbScanReceiver.cpp
deleted file mode 100644
index 6c8c16c3ecf..00000000000
--- a/ndb/src/ndbapi/NdbScanReceiver.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/* 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; either version 2 of the License, or
-   (at your option) any later version.
-
-   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 */
-
-#include "NdbScanReceiver.hpp"
-#include <NdbRecAttr.hpp>
-
-#include <signaldata/ScanFrag.hpp>
-
-#include <NdbOut.hpp>
-
-
-/***************************************************************************
- * int receiveKEYINFO20( NdbApiSignal* aSignal)
- *
- * Remark:  Handles the reception of the KEYINFO20 signal. 
- *          Save a copy of the signal in list
- *
- ***************************************************************************/
-int
-NdbScanReceiver::receiveKEYINFO20( NdbApiSignal* aSignal){
-  const KeyInfo20 * const keyInfo = CAST_CONSTPTR(KeyInfo20, aSignal->getDataPtr());
-  if (theStatus !=  Waiting){
-    //ndbout << "Dropping KEYINFO20, theStatus="<<theStatus << endl;
-    return -1;
-  }
-  if (aSignal->getLength() < 5){
-    //ndbout << "Dropping KEYINFO20, length="<<aSignal->getLength() << endl;
-  }
-  Uint64 tCurrTransId = theNdbOp->theNdbCon->getTransactionId();
-  Uint64 tRecTransId = (Uint64)keyInfo->transId1 + ((Uint64)keyInfo->transId2 << 32);
-  if ((tRecTransId - tCurrTransId) != (Uint64)0){
-    //ndbout << "Dropping KEYINFO20 wrong transid" << endl;
-    return -1;
-  }
-
-  NdbApiSignal * tCopy = new NdbApiSignal(0);//getSignal();
-  if (tCopy == NULL) {
-    theNdbOp->setErrorCode(4000);
-    return 2; // theWaitState = NO_WAIT
-  } 
-  // Put copy last in list of KEYINFO20 signals
-  tCopy->copyFrom(aSignal);
-  tCopy->next(NULL);
-  if (theFirstKEYINFO20_Recv == NULL)
-    theFirstKEYINFO20_Recv = tCopy;
-  else
-    theLastKEYINFO20_Recv->next(tCopy);
-  theLastKEYINFO20_Recv = tCopy;
-
-  theTotalKI_Len = keyInfo->keyLen; // This is the total length of all signals
-  theTotalRecKI_Len += aSignal->getLength() - 5;    
-  return theNdbOp->theNdbCon->checkNextScanResultComplete();
-}
-
-/***************************************************************************
- * int receiveTRANSID_AI_SCAN( NdbApiSignal* aSignal)
- *
- * Remark:  Handles the reception of the TRANSID_AI_signal with 
- *          22 signal data words.
- *          Save a copy of the signal in list and check if all 
- *          signals belonging to this resultset is receieved.
- *
- ***************************************************************************/
-int
-NdbScanReceiver::receiveTRANSID_AI_SCAN( NdbApiSignal* aSignal)
-{
-  const Uint32* aDataPtr = aSignal->getDataPtr();
-  if (theStatus !=  Waiting){
-    //ndbout << "Dropping TRANSID_AI, theStatus="<<theStatus << endl;
-    return -1;
-  }
-  if (aSignal->getLength() < 3){
-    //ndbout << "Dropping TRANSID_AI, length="<<aSignal->getLength() << endl;
-    return -1;
-  }
-  if (theNdbOp == NULL){
-    //ndbout << "Dropping TRANSID_AI, theNdbOp == NULL" << endl;
-    return -1;
-  }
-  if (theNdbOp->theNdbCon == NULL){
-    //ndbout << "Dropping TRANSID_AI, theNdbOp->theNdbCon == NULL" << endl;
-    return -1;
-  }
-  Uint64 tCurrTransId = theNdbOp->theNdbCon->getTransactionId();
-  Uint64 tRecTransId = (Uint64)aDataPtr[1] + ((Uint64)aDataPtr[2] << 32);
-  if ((tRecTransId - tCurrTransId) != (Uint64)0){
-    //ndbout << "Dropping TRANSID_AI wrong transid" << endl;
-    return -1;
-  }
-
-  NdbApiSignal * tCopy = new NdbApiSignal(0);//getSignal();
-  if (tCopy == NULL){
-    theNdbOp->setErrorCode(4000);
-    return 2; // theWaitState = NO_WAIT
-  }
-  tCopy->copyFrom(aSignal);
-  tCopy->next(NULL);
-  if (theFirstTRANSID_AI_Recv == NULL)
-      theFirstTRANSID_AI_Recv = tCopy;
-  else
-      theLastTRANSID_AI_Recv->next(tCopy);
-  theLastTRANSID_AI_Recv = tCopy;
-  theTotalRecAI_Len += aSignal->getLength() - 3;    
-
-  return theNdbOp->theNdbCon->checkNextScanResultComplete();
-}
-
-/***************************************************************************
- * int executeSavedSignals()
- *
- * Remark:  Execute all saved TRANSID_AI signals into the parent NdbOperation
- *          
- *
- ***************************************************************************/
-int
-NdbScanReceiver::executeSavedSignals(){
-
-  NdbApiSignal* tSignal = theFirstTRANSID_AI_Recv;
-  while (tSignal != NULL) {
-    const Uint32* tDataPtr = tSignal->getDataPtr();
-    
-    int tRet = theNdbOp->receiveREAD_AI((Uint32*)&tDataPtr[3], 
-					tSignal->getLength() - 3);
-    if (tRet != -1){
-      // -1 means that more signals are wanted ?
-      // Make sure there are no more signals in the list
-      assert(tSignal->next() == NULL);
-    }
-    tSignal = tSignal->next();
-  }
-  // receiveREAD_AI may not copy to application buffers
-  NdbRecAttr* tRecAttr = theNdbOp->theFirstRecAttr;
-  while (tRecAttr != NULL) {
-    if (tRecAttr->copyoutRequired())    // copy to application buffer
-      tRecAttr->copyout();
-    tRecAttr = tRecAttr->next();
-  }
-  // Release TRANSID_AI signals for this receiver
-  while(theFirstTRANSID_AI_Recv != NULL){
-    NdbApiSignal* tmp = theFirstTRANSID_AI_Recv;
-    theFirstTRANSID_AI_Recv = tmp->next();
-    delete tmp;
-  }
-
-  //  theNdbOp->theNdb->releaseSignalsInList(&theFirstTRANSID_AI_Recv);
-  theFirstTRANSID_AI_Recv = NULL;
-  theLastTRANSID_AI_Recv = NULL;
-  theStatus = Executed;
-
-  return 0;
-}
-
-
-void 
-NdbScanReceiver::prepareNextScanResult(){
-  if(theStatus == Executed){
-
-    // theNdbOp->theNdb->releaseSignalsInList(&theFirstKEYINFO20_Recv);
-    while(theFirstKEYINFO20_Recv != NULL){
-      NdbApiSignal* tmp = theFirstKEYINFO20_Recv;
-      theFirstKEYINFO20_Recv = tmp->next();
-      delete tmp;
-    }
-    theFirstKEYINFO20_Recv = NULL;
-    theLastKEYINFO20_Recv = NULL;
-    theTotalRecAI_Len = 0;
-    theTotalRecKI_Len = 0;
-    if (theLockMode == true)
-      theTotalKI_Len = 0xFFFFFFFF;
-    else
-      theTotalKI_Len = 0;
-    theStatus = Waiting;
-  }
-}
diff --git a/ndb/src/ndbapi/NdbScanReceiver.hpp b/ndb/src/ndbapi/NdbScanReceiver.hpp
deleted file mode 100644
index 72f9e48f02c..00000000000
--- a/ndb/src/ndbapi/NdbScanReceiver.hpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/* 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; either version 2 of the License, or
-   (at your option) any later version.
-
-   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 NdbScanReceiver_H
-#define NdbScanReceiver_H
-
-#include "Ndb.hpp"
-#include "NdbConnection.hpp"
-#include "NdbOperation.hpp"
-#include "NdbApiSignal.hpp"
-#include "NdbReceiver.hpp"
-#include <NdbOut.hpp>
-
-
-class NdbScanReceiver
-{
-  enum ReceiverStatus	{ Init,
-			  Waiting,
-			  Completed,
-			  Executed,
-			  Released };
-
-  friend class Ndb;
-  friend class NdbOperation;
-public:
-  NdbScanReceiver(Ndb *aNdb) : 
-    theReceiver(aNdb),
-    theNdbOp(NULL),
-    theFirstTRANSID_AI_Recv(NULL), 
-    theLastTRANSID_AI_Recv(NULL),
-    theFirstKEYINFO20_Recv(NULL),
-    theLastKEYINFO20_Recv(NULL),
-    theTotalRecAI_Len(0),
-    theTotalKI_Len(0xFFFFFFFF),
-    theTotalRecKI_Len(0),
-    theStatus(Init),
-    theNextScanRec(NULL)  
-  {
-    theReceiver.init(NdbReceiver::NDB_SCANRECEIVER, this);
-  }
-
-  int	 checkMagicNumber();
-  int	 receiveTRANSID_AI_SCAN(NdbApiSignal*);
-  int	 receiveKEYINFO20(NdbApiSignal*);
-  int    executeSavedSignals();
-  void   prepareNextScanResult();
-
-  NdbScanReceiver* next();
-  void  next(NdbScanReceiver*);
-
-  bool isCompleted(Uint32 aiLenToReceive);
-  void setCompleted();
-
-  void init(NdbOperation* aNdbOp, bool lockMode);
-
-  Uint32 ptr2int() { return theReceiver.getId(); };
-private:
-  NdbScanReceiver();
-  void release();
-
-  NdbReceiver  theReceiver;
-
-  NdbOperation*       theNdbOp;
-  NdbApiSignal*       theFirstTRANSID_AI_Recv; 
-  NdbApiSignal*       theLastTRANSID_AI_Recv;
-  NdbApiSignal*       theFirstKEYINFO20_Recv; 
-  NdbApiSignal*       theLastKEYINFO20_Recv;
-
-  Uint32              theTotalRecAI_Len;
-  Uint32              theTotalKI_Len;
-  Uint32              theTotalRecKI_Len;
-  ReceiverStatus      theStatus;
-  Uint32              theMagicNumber; 
-  NdbScanReceiver*    theNextScanRec;
-  bool                theLockMode;
-
-};
-
-inline 
-void 
-NdbScanReceiver::init(NdbOperation* aNdbOp, bool lockMode){
-    assert(theStatus == Init || theStatus == Released); 
-    theNdbOp = aNdbOp;
-    theMagicNumber = 0xA0B1C2D3;
-    theTotalRecAI_Len = 0;
-
-    /* If we are locking the records for take over 
-     * KI_len to receive is at least 1, since we don't know yet 
-     * how much KI we are expecting(this is written in the first KI signal)
-     * set theTotalKI_Len to FFFFFFFF, this will make the ScanReciever wait for 
-     * at least the first KI, and when that is received we will know if 
-     * we are expecting another one
-     */
-    theLockMode = lockMode;
-    if (theLockMode == true)
-      theTotalKI_Len = 0xFFFFFFFF;
-    else
-      theTotalKI_Len = 0;
-    theTotalRecKI_Len = 0;
-
-    assert(theNextScanRec == NULL);
-    theNextScanRec = NULL;
-    assert(theFirstTRANSID_AI_Recv == NULL);
-    theFirstTRANSID_AI_Recv = NULL;
-    assert(theLastTRANSID_AI_Recv == NULL);
-    theLastTRANSID_AI_Recv = NULL;
-    assert(theFirstKEYINFO20_Recv == NULL);
-    theFirstKEYINFO20_Recv = NULL;
-    theLastKEYINFO20_Recv = NULL;
-    
-    theStatus = Waiting;
-};
-
-
-inline 
-void 
-NdbScanReceiver::release(){
-  theStatus = Released;
-  //  theNdbOp->theNdb->releaseSignalsInList(&theFirstTRANSID_AI_Recv);
-  while(theFirstTRANSID_AI_Recv != NULL){
-    NdbApiSignal* tmp = theFirstTRANSID_AI_Recv;
-    theFirstTRANSID_AI_Recv = tmp->next();
-    delete tmp;
-  }
-  theFirstTRANSID_AI_Recv = NULL;
-  theLastTRANSID_AI_Recv = NULL;
-  //  theNdbOp->theNdb->releaseSignalsInList(&theFirstKEYINFO20_Recv);
-  while(theFirstKEYINFO20_Recv != NULL){
-    NdbApiSignal* tmp = theFirstKEYINFO20_Recv;
-    theFirstKEYINFO20_Recv = tmp->next();
-    delete tmp;
-  }
-  theFirstKEYINFO20_Recv = NULL;
-  theLastKEYINFO20_Recv = NULL;
-  theNdbOp = NULL;
-  theTotalRecAI_Len = 0;
-  theTotalRecKI_Len = 0;
-  theTotalKI_Len = 0xFFFFFFFF;
-};
-
-inline
-int
-NdbScanReceiver::checkMagicNumber()
-{
-  if (theMagicNumber != 0xA0B1C2D3)
-    return -1;
-  return 0;
-}
-
-inline 
-NdbScanReceiver*
-NdbScanReceiver::next(){
-  return theNextScanRec;
-}
-
-inline 
-void
-NdbScanReceiver::next(NdbScanReceiver* aScanRec){
-  theNextScanRec = aScanRec;
-}
-
-inline 
-bool
-NdbScanReceiver::isCompleted(Uint32 aiLenToReceive){
-  assert(theStatus == Waiting || theStatus == Completed);
-#if 0
-  ndbout << "NdbScanReceiver::isCompleted"<<endl
-	 << "  theStatus = " << theStatus << endl
-	 << "  theTotalRecAI_Len = " << theTotalRecAI_Len << endl
-	 << "  aiLenToReceive = " << aiLenToReceive << endl
-	 << "  theTotalRecKI_Len = "<< theTotalRecKI_Len << endl
-	 << "  theTotalKI_Len = "<< theTotalKI_Len << endl;
-#endif
-  // Have we already receive everything
-  if(theStatus == Completed)
-    return true;
-
-  // Check that we have received AI
-  if(theTotalRecAI_Len < aiLenToReceive)
-    return false;
-
-  // Check that we have recieved KI
-  if (theTotalRecKI_Len < theTotalKI_Len)
-    return false;
-
-  // We should not have recieved more AI
-  assert(theTotalRecAI_Len <= aiLenToReceive);
-  return true;  
-}
-
-inline 
-void
-NdbScanReceiver::setCompleted(){
-  theStatus = Completed;
-}
-
-#endif
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index fd357ef4e37..6be43057af3 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -240,10 +240,6 @@ Ndb::~Ndb()
 //    closeSchemaTransaction(theSchemaConToNdbList);
   while ( theConIdleList != NULL )
     freeNdbCon();
-  while ( theSignalIdleList != NULL )
-    freeSignal();
-  while (theRecAttrIdleList != NULL)
-    freeRecAttr(); 
   while (theOpIdleList != NULL)
     freeOperation();
   while (theScanOpIdleList != NULL)
@@ -262,6 +258,10 @@ Ndb::~Ndb()
     freeNdbScanRec();
   while (theNdbBlobIdleList != NULL)
     freeNdbBlob();
+  while (theRecAttrIdleList != NULL)
+    freeRecAttr(); 
+  while ( theSignalIdleList != NULL )
+    freeSignal();
   
   releaseTransactionArrays();
   startTransactionNodeSelectionData.release();
-- 
2.30.9