Commit 892b5c9b authored by unknown's avatar unknown
Browse files

Fix memory leak


BitKeeper/deleted/.del-NdbScanReceiver.hpp~5c295814a47e7bb4:
  Delete: ndb/src/ndbapi/NdbScanReceiver.hpp
BitKeeper/deleted/.del-NdbScanReceiver.cpp~b8a7472e4a7c424f:
  Delete: ndb/src/ndbapi/NdbScanReceiver.cpp
ndb/include/ndb_global.h:
  Added ndb_end (corresponding to ndb_init)
ndb/src/common/util/ndb_init.c:
  Added ndb_end (corresponding to ndb_init)
ndb/src/ndbapi/NdbScanOperation.cpp:
  Release SCAN_TABREQ and 
  make sure to call NdbOperation::release (that releases other stuff)
ndb/src/ndbapi/Ndbinit.cpp:
  Reorder free-ing so that signal are release last
  (so that operations holding signals can release the first)
parent d6c1a39a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -27,3 +27,9 @@ ndb_init()
  }
  return 0;
}

void
ndb_end(int flags)
{
  my_end(flags);
}
+8 −1
Original line number Diff line number Diff line
@@ -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();
}

/***************************************************************************
+0 −187
Original line number Diff line number Diff line
/* 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;
  }
}
+0 −210
Original line number Diff line number Diff line
/* 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
Loading