mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 18:20:07 +01:00
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)
This commit is contained in:
parent
d6c1a39a15
commit
892b5c9bca
6 changed files with 19 additions and 402 deletions
|
@ -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);
|
||||
|
|
|
@ -27,3 +27,9 @@ ndb_init()
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ndb_end(int flags)
|
||||
{
|
||||
my_end(flags);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue