Commit 106d203f authored by joreland@mysql.com's avatar joreland@mysql.com

Fix memory leak

parent 71d5ea8f
...@@ -78,6 +78,7 @@ extern "C" { ...@@ -78,6 +78,7 @@ extern "C" {
/* call in main() - does not return on error */ /* call in main() - does not return on error */
extern int ndb_init(void); extern int ndb_init(void);
extern void ndb_end(int);
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
extern char * strdup(const char *s); extern char * strdup(const char *s);
......
...@@ -27,3 +27,9 @@ ndb_init() ...@@ -27,3 +27,9 @@ ndb_init()
} }
return 0; return 0;
} }
void
ndb_end(int flags)
{
my_end(flags);
}
...@@ -52,6 +52,7 @@ NdbScanOperation::NdbScanOperation(Ndb* aNdb) : ...@@ -52,6 +52,7 @@ NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
NdbScanOperation::~NdbScanOperation() NdbScanOperation::~NdbScanOperation()
{ {
for(Uint32 i = 0; i<m_allocated_receivers; i++){ for(Uint32 i = 0; i<m_allocated_receivers; i++){
m_receivers[i]->release();
theNdb->releaseNdbScanRec(m_receivers[i]); theNdb->releaseNdbScanRec(m_receivers[i]);
} }
delete[] m_array; delete[] m_array;
...@@ -191,7 +192,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm, ...@@ -191,7 +192,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
return 0; return 0;
} }
theSCAN_TABREQ = theNdb->getSignal(); theSCAN_TABREQ = (!theSCAN_TABREQ ? theNdb->getSignal() : theSCAN_TABREQ);
if (theSCAN_TABREQ == NULL) { if (theSCAN_TABREQ == NULL) {
setErrorCodeAbort(4000); setErrorCodeAbort(4000);
return 0; return 0;
...@@ -719,6 +720,12 @@ void NdbScanOperation::release() ...@@ -719,6 +720,12 @@ void NdbScanOperation::release()
for(Uint32 i = 0; i<m_allocated_receivers; i++){ for(Uint32 i = 0; i<m_allocated_receivers; i++){
m_receivers[i]->release(); m_receivers[i]->release();
} }
if(theSCAN_TABREQ)
{
theNdb->releaseSignal(theSCAN_TABREQ);
theSCAN_TABREQ = 0;
}
NdbOperation::release();
} }
/*************************************************************************** /***************************************************************************
......
/* 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;
}
}
/* 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
...@@ -240,10 +240,6 @@ Ndb::~Ndb() ...@@ -240,10 +240,6 @@ Ndb::~Ndb()
// closeSchemaTransaction(theSchemaConToNdbList); // closeSchemaTransaction(theSchemaConToNdbList);
while ( theConIdleList != NULL ) while ( theConIdleList != NULL )
freeNdbCon(); freeNdbCon();
while ( theSignalIdleList != NULL )
freeSignal();
while (theRecAttrIdleList != NULL)
freeRecAttr();
while (theOpIdleList != NULL) while (theOpIdleList != NULL)
freeOperation(); freeOperation();
while (theScanOpIdleList != NULL) while (theScanOpIdleList != NULL)
...@@ -262,6 +258,10 @@ Ndb::~Ndb() ...@@ -262,6 +258,10 @@ Ndb::~Ndb()
freeNdbScanRec(); freeNdbScanRec();
while (theNdbBlobIdleList != NULL) while (theNdbBlobIdleList != NULL)
freeNdbBlob(); freeNdbBlob();
while (theRecAttrIdleList != NULL)
freeRecAttr();
while ( theSignalIdleList != NULL )
freeSignal();
releaseTransactionArrays(); releaseTransactionArrays();
startTransactionNodeSelectionData.release(); startTransactionNodeSelectionData.release();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment